• poj1741 Tree(点分治)


    题目链接:http://poj.org/problem?id=1741

    题意:求树上两点之间距离小于等于k的点对的数量

    思路:点分治模板题,推荐一篇讲的非常好的博客:https://blog.csdn.net/qq_39553725/article/details/77542223

    实现代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define inf 0x7fffffff
    #define rson m+1,r,rt<<1|1
    #define mid int m = (l + r) >> 1
    const int M = 1e5+10;
    struct node{
        int to,w,next;
    }e[M<<2];
    int n,m;
    int vis[M],dis[M],d[M],siz[M],f[M],cnt,head[M],sum,root,k,ans;
    void init(){
        cnt = 0;
        ans = 0;
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
    }
    
    void add(int u,int v,int w){
        e[++cnt].to=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;
    }
    
    
    void get_root(int u,int fa){
        siz[u] = 1; f[u] = 0;
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v!=fa&&!vis[v]){
                get_root(v,u);
                siz[u] += siz[v];
                f[u] = max(f[u],siz[v]);
            }
        }
        // cout<<"sum:  "<<sum-siz[v]<<endl
        f[u] = max(f[u],sum - siz[u]);
        if(f[u] < f[root]) root = u;
        return ;
    }
    
    void get_dis(int u,int fa){
        dis[++dis[0]] = d[u];
        for(int i = head[u];i;i = e[i].next){
            int v = e[i].to;
            if(v != fa&& !vis[v]){
                d[v] = d[u] + e[i].w;
                get_dis(v,u);
            }
        }
        return;
    }
    
    int cal(int u,int c){
        d[u] =  c; dis[0] = 0;
        get_dis(u,0);
        sort(dis+1,dis+dis[0]+1);
        int l = 1,r = dis[0],sum = 0;
        while(l < r){
            if(dis[l] + dis[r] <= k){
                sum+=r-l;
                l ++;
            }
            else r--;
        }
        return sum;
    }
    
    void solve(int u){
        ans += cal(u,0);
        vis[u] = 1;
        for(int i = head[u];i;i = e[i].next){
            int v = e[i].to;
            if(!vis[v]){
                ans -= cal(v,e[i].w);
                sum = siz[v] ;
                root = 0;
                get_root(v,0);
                solve(root);
            }
        }
    }
    int main()
    {
        int u,v,w;
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        while(cin>>n>>k){
        if(n==0&&m==0) break;
        init();
        for(int i = 1;i <= n-1;i ++){
            cin>>u>>v>>w;
            add(u,v,w); add(v,u,w);
        }
        f[0] = inf;
        sum = n;
        root = 0;
        get_root(1,0);
        solve(root);
        cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    lamp
    mysql多实例部署
    mysql进阶
    rsync
    mysql基础
    httpd
    ftp
    高级命令之awk
    NFS
    网络进阶管理
  • 原文地址:https://www.cnblogs.com/kls123/p/9317113.html
Copyright © 2020-2023  润新知