• 树上点分治 poj 1741


    Give a tree with n vertices,each edge has a length(positive integer less than 1001).
    Define dist(u,v)=The min distance between node u and v.
    Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
    Write a program that will count how many pairs which are valid for a given tree.
    Input
    The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
    The last test case is followed by two zeros.
    Output
    For each test case output the answer on a single line.
    Sample Input
    5 4
    1 2 3
    1 3 1
    1 4 2
    3 5 1
    0 0
    
    Sample Output
    8
    题目分析 : 给定一棵树,以及树上边的关系大小,问你又多少对点的距离是小于等于所给定的 d 的
    思路分析 : 树上点分治的板子题,首先寻找树的重心,以重心为根结点,寻求所有符合题意要求的点对,但是这样计算会算出一些不符合题目的点对,在减去即可,此时当遍历到一个新的结点时,此时的情况又可以当成最初的情况,找重心的时候要注意,对它的子树来说,总的结点数是小于 n 的!!!
          最后的复杂度是n logn logn    其中每次快排是nlogn 而递归的深度为logn
    代码示例 :
    const int maxn = 1e4+5;
    const int inf = 0x3f3f3f3f;
    #define ll long long
    
    int n, m;
    struct node
    {
        int to, cost;
        node(int _to = 0, int _cost = 0):to(_to), cost(_cost){}
    };
    vector<node>ve[maxn];
    int root;
    int size[maxn], mx[maxn]; // size表示每个结点所连的结点数, mx表示对每个根结点所连的最大结点子树有多少的结点
    int balance;
    bool done[maxn];
    int ans = 0;
    int numm; // 表示结点总数
    
    void getroot(int x, int fa){
        size[x] = 1, mx[x] = 0;
    
        for(int i = 0; i < ve[x].size(); i++){
            int to = ve[x][i].to;
            if (to == fa || done[to]) continue;
            getroot(to, x);
            size[x] += size[to];  
            mx[x] = max(mx[x], size[to]);
        }    
        mx[x] = max(mx[x], numm-size[x]); // 对子树在寻找子树的重心的过程中,子树的总结点数是会变小的
        if (mx[x] < balance) {balance = mx[x], root = x;}
    }
    
    int cnt = 0;
    int dep[maxn];
    void dfssize(int x, int fa, int d){
        dep[cnt++] = d;
        
        for(int i = 0; i < ve[x].size(); i++){
            int to = ve[x][i].to;
            int cost = ve[x][i].cost;
            if (to == fa || done[to]) continue;
            dfssize(to, x, d+cost); 
        }
    }
    
    int cal(int x, int d){
        cnt = 0;
        dfssize(x, x, d);
        sort(dep, dep+cnt);
        int l = 0, r = cnt-1;
        int sum = 0;
        
        while(l < r){
            if (dep[l]+dep[r] <= m){
                sum += r-l;
                l++;        
            }
            else r--;
        }
        //printf("sum = %d 
    ", sum);
        //system("pause");
        return sum;
    }
    
    void dfs(int x){
        done[x] = true;
        ans += cal(x, 0);
         
        for(int i = 0; i < ve[x].size(); i++){
            int to = ve[x][i].to;
            int cost = ve[x][i].cost;
            
            if (done[to]) continue;
            ans -= cal(to, cost);
            balance = inf;
            numm = size[to]; // 这里是重点,因为这个地方一直T,还以为写的代码有问题
            getroot(to, to);
            //printf("root = %d
    ", root);
            dfs(root);
        }
    }
    
    int a, b, w;
    int main() {
        while(scanf("%d%d", &n, &m) && n+m){
            for(int i = 0; i <= 10000; i++) ve[i].clear();
            memset(done, false, sizeof(done));
            for(int i = 1; i < n; i++){
                scanf("%d%d%d", &a, &b, &w);
                ve[a].push_back(node(b, w));
                ve[b].push_back(node(a, w));            
            }
            ans = 0;
            balance = inf;
            numm = n;
            getroot(1, 1);
            //printf("root = %d
    ", root);         
            dfs(root);
            printf("%d
    ", ans);
        }
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    【HDU3681】Prison Break-状态压缩DP+BFS+二分答案
    【BashuOJ3520】警察局长-最短路树+树上背包+概率DP
    【POJ1201】Intervals-差分约束系统+单源最长路
    【BashuOJ2041】最大矩形-矩阵型DP
    【BashuOJ2041】最大矩形-矩阵型DP
    deleted
    deleted
    deleted
    deleted
    deleted
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8481441.html
Copyright © 2020-2023  润新知