zoukankan      html  css  js  c++  java
  • POJ 1741 Tree 树分治

    Tree

    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    http://poj.org/problem?id=1741

    Description

    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

    HINT

    题意

    给你一颗树,问你有多少个对点的距离小于k

    题解:

    树分治,可以去看漆子超的论文,讲的很详细

    http://wenku.baidu.com/link?url=7KOPn20aLvKK5PqDmuLjIyj4sqZ6CL1H9qP__JSGvX-AWgX7LR6gC-BZ3PTVCP2ojBHxKZcJ5U3csiRjuspqcoFJfswO7JaEIQyKlxwUzBi

    代码

    #include<iostream>
    #include<stdio.h>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    #define mem(a,b) memset(a,b,sizeof(a))
    #define maxn 10005
    struct Edge{
        int v,w;
        Edge(){}
        Edge(int v1,int w1):v(v1),w(w1){}
        bool operator<(const Edge& other) const {
            return w < other.w;
        }
    };
    vector<Edge> e[maxn];
    int n,k;
    int sum,root,ans,cnt;
    int f[maxn],vis[maxn],son[maxn],d[maxn],deep[maxn];
    void init() {
        root = ans = cnt = 0;
        for(int i=0;i<maxn;i++) e[i].clear();
        mem(vis,0); mem(f,0); mem(son,0); mem(d,0); mem(deep,0);
    }
    
    void getroot(int u,int fa) {
        son[u]=1;f[u]=0;
        for(int i=0;i<e[u].size();i++) {
            int v = e[u][i].v;
            if(v == fa || vis[v]) continue;
            getroot(v,u);
            son[u] += son[v];
            f[u] = max(f[u], son[v]);
        }
        f[u]=max(f[u],sum-f[u]);
        //f[u] 最后求得是以u为根的最大子树的size
        //当前树的root 应该是重心
        //重心是f[u] 最小的
        if(f[u] < f[root]) root=u;
    }
    void getdeep(int u,int fa) {
        deep[++deep[0]] = d[u];
        for(int i=0;i<e[u].size();i++) {
            int v = e[u][i].v, w = e[u][i].w;
            if(v==fa || vis[v]) continue;
            d[v] = d[u] + w;
            getdeep(v,u);
        }
    }
    int cal(int u,int now) {
        d[u]=now; deep[0]=0;
        getdeep(u,0);
        sort(deep+1,deep+deep[0]+1);
        int t=0,l=1,r=deep[0];
        while (l < r) {
            if(deep[l] + deep[r] <=k)
                t+= r-l, l++;
            else
                r--;
        }
        return t;
    }
    
    void solve(int u) {
        //计算经过树根u 的 deep[l] + deep[r] <= k
        //但因为经过树根u 的配对点(l,r) 可能不用经过u能 <=k,所以应该去除
        //所以每次ans应该计算的是两个不同子树的节点l,r 使得 deep[l] + deep[r] <= k
        ans += cal(u,0);
        vis[u] = 1;
        for(int i=0;i<e[u].size();i++) {
            int v = e[u][i].v, w = e[u][i].w;
            if(vis[v]) continue;
            ans -= cal(v,w);
            sum = son[v];
            root = 0;
            getroot(v,root);
            solve(root);
        }
    }
    
    int main () {
        while (scanf("%d %d",&n,&k) != EOF) {
            if(n==0&&k==0) break;
            init();
            for(int i=1;i<n;i++) {
                int u,v,w; scanf("%d %d %d",&u,&v,&w);
                e[u].push_back(Edge(v,w));
                e[v].push_back(Edge(u,w));
            }
            sum=n,f[0]=0x3f3f3f3f;
            getroot(1,0);
            solve(root);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    IIS配置Asp.net时,出现“未能加载文件或程序集“System.Web.Extensions.Design, Version=1.0.61025.0”
    如何ping测有端口的网站
    职场情况--小领导人品不好,大领导很欣赏我,该不该将小领导的搓事告诉大领导?
    https://www.cnblogs.com/netoxi/p/7258895.html
    java基本数据类型
    不用犹豫什么时候声明实例变量或者拒不变量
    java多线程
    架构考虑
    多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify())
    csrf攻击
  • 原文地址:https://www.cnblogs.com/Draymonder/p/9498106.html
Copyright © 2011-2022 走看看