zoukankan      html  css  js  c++  java
  • [LUOGU4149][IOI2011]Race

    题目描述

    给一棵树,每条边有权。求一条简单路径,权值和等于 KKK ,且边的数量最小。

    输入输出格式

    输入格式:

    第一行:两个整数 n,kn,kn,k 。

    第二至 nnn 行:每行三个整数,表示一条无向边的两端和权值 (注意点的编号从 000 开始)。

    输出格式:

    一个整数,表示最小边数量。

    如果不存在这样的路径,输出 −1-11 。

    输入输出样例

    输入样例#1: 
    4 3
    0 1 1
    1 2 2
    1 3 4
    输出样例#1: 
    2

    说明

    n≤200000,K≤1000000nle 200000,Kle 1000000n200000,K1000000 。


     
    点分治, 记录路径长度为i的最小经过路径, 然后就是正常的点分治。
    之后记得把上面说的数组赋成正无穷, 这个不能暴力清空, 否则复杂度退化。
     

     
     
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    inline int read() {
        int res=0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
        return res;
    }
    #define reg register
    #define N 200005
    int n, tot, k;
    struct edge {
        int nxt, to, val;
    }ed[N*2];
    int head[N], cnt = 1;
    inline void add(int x, int y, int z)
    {
        ed[++cnt] = (edge){head[x], y, z};
        head[x] = cnt;
    }
    
    bool cut[N*2];
    int siz[N], root, mrt = 1e9, maxx[N];
    void dfs(int x, int fa)
    {
        siz[x] = 1;
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == fa or cut[i]) continue;
            dfs(to, x);
            siz[x] += siz[to];
        }    
    }
    
    void efs(int x, int fa)
    {
        int tmp = tot - siz[x];
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == fa or cut[i]) continue;
            efs(to, x);
            tmp = max(tmp, siz[to]);
        }
        if (tmp < mrt) mrt = tmp, root = x;
    }
    
    inline int FindRoot(int x)
    {
        dfs(x, 0);
        mrt = 1e9;
        tot = siz[x];
        root = n;
        efs(x, 0);
        return root;
    }
    
    int ans = 1e9;
    int dep[N], len[1000005], dis[N];//深度|长为i的最小深度|长度 
    
    void Work(int x, int fa)
    {
        if (dis[x] > k) return ;
        if (len[k - dis[x]] != 0x3f3f3f3f) 
            if (dep[x] + len[k - dis[x]] <= ans) ans = dep[x] + len[k - dis[x]];
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (cut[i] or to == fa) continue;
            dep[to] = dep[x] + 1;
            dis[to] = dis[x] + ed[i].val;
        //    len[dis[to]] = min(len[dis[to]], dep[to]);
            Work(to, x);
        }
    }
    
    void Pushup(int x, int fa, bool opt)
    {
        if (dis[x] > k) return;
        if (opt) len[dis[x]] = 0x3f3f3f3f; 
        else len[dis[x]] = min(len[dis[x]], dep[x]);
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == fa or cut[i]) continue;
            Pushup(to, x, opt);
        }
    }
    
    void solve(int rt)
    {
        root = FindRoot(rt);
        len[0] = 0;
        //memset(len, 0x3f, sizeof len);
        for (reg int i = head[root] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (cut[i])  continue;
            dep[root] = 0, dep[to] = 1;
            dis[root] = 0, dis[to] = ed[i].val;
            Work(to, root);
            Pushup(to, root, 0);
        }
        for (reg int i = head[root] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (cut[i]) continue;
            Pushup(to, root, 1);
        }
        for (reg int i = head[root] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (cut[i]) continue;
            cut[i] = cut[i ^ 1] = 1;
            solve(to);
        }
    }
    
    int main()
    {
        n = read(), k = read();
        for (reg int i = 1 ; i < n ; i ++)
        {
            int x = read(), y = read(), z = read();
            add(x + 1, y + 1, z), add(y + 1, x + 1, z);
        }
        memset(len, 0x3f, sizeof len);
        solve(1);
        if (ans == 1e9) ans = -1;
        printf("%d
    ", ans);
        return 0;
    }
     
     
     
  • 相关阅读:
    Codeforces 691A Fashion in Berland
    HDU 5741 Helter Skelter
    HDU 5735 Born Slippy
    HDU 5739 Fantasia
    HDU 5738 Eureka
    HDU 5734 Acperience
    HDU 5742 It's All In The Mind
    POJ Euro Efficiency 1252
    AtCoder Beginner Contest 067 C
    AtCoder Beginner Contest 067 D
  • 原文地址:https://www.cnblogs.com/BriMon/p/9478093.html
Copyright © 2011-2022 走看看