• [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;
    }
     
     
     
  • 相关阅读:
    Leetcode Word Pattern
    Leetcode Strobogrammatic Number
    Leetcode Meeting Rooms
    Leetcode Pascal's Triangle II
    Leetcode Pascal's Triangle
    Leetcode Majority Element II
    Leetcode Majority Element
    牛客多校第六场 B Shorten IPv6 Address 模拟
    牛客多校第六场 A Garbage 模拟/签到
    排列数,康托展开及其线段树优化
  • 原文地址:https://www.cnblogs.com/BriMon/p/9478093.html
Copyright © 2020-2023  润新知