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

    Tree
     
     

    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

    题意:

      给你一个含有n个节点的树,每条边有权值,问你有多少点对最短路径不超过k

     

    题解:

      树分治入门题

      推荐看09年ioi的论文

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int N = 1e5+20, M = 1e2+10, mod = 1e9+7, inf = 1e9+1000;
    typedef long long ll;
    
    int n,m,root,t,ans,allnode,siz[N],K,head[N],vis[N],d[N];
    int deep[N];//路径长度//deep[0]子节点个数
    int f[N];//重心
    
    struct edg{int to,next,v;}e[N * 4];//前向星存边
    void add(int u,int v,int w) {e[t].to=v;e[t].next=head[u];e[t].v=w;head[u]=t++;}//加边
    
    //获取重心
    void getroot(int x,int fa) {
        siz[x] = 1;
        f[x] = 0;
        for(int i=head[x];i;i=e[i].next) {
            int to = e[i].to;
            if(to == fa || vis[to]) continue;
            getroot(to,x);
            siz[x] += siz[to];
            f[x] = max(f[x] , siz[to]);
        }
        f[x] = max(allnode-siz[x] , f[x]);
        if(f[x] < f[root]) root = x;
    }
    
    void getdeep(int x,int fa) {//获取子树所有节点与根的距离
        deep[++deep[0]] = d[x];
        for(int i=head[x];i;i=e[i].next) {
            int to = e[i].to;
            if(to == fa || vis[to]) continue;
            d[to] = d[x] + e[i].v;
            getdeep(to,x);
        }
    }
    int cal(int x,int now) {//计算当前以重心x的子树下,所有情况的答案
        d[x]=now;deep[0]=0;
        getdeep(x,0);
        sort(deep+1,deep+deep[0]+1);
        int all = 0;
        for(int l=1,r=deep[0];l<r;) {
            if(deep[l]+deep[r] <= K) {all += r-l;l++;}
            else r--;
        }
        return all;
    }
    
    void work(int x) {//以x为重心进行计算
        vis[x] = 1;
        ans+=cal(x,0);
        for(int i=head[x];i;i=e[i].next) {
            int to = e[i].to;
            if(vis[to]) continue;
            ans -= cal(to,e[i].v);
            allnode = siz[to];
            root=0;
            getroot(to,x);
            work(root);
        }
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&K)) {
            if(!n&&!m) break;
            memset(head,0,sizeof(head));
            memset(vis,0,sizeof(vis));
            t = 1;
            for(int i=1;i<n;i++) {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c) , add(b,a,c);
            }
            root=ans=0;
            allnode=n;f[0]=inf;
            getroot(1,0);
            work(root);
            printf("%d
    ",ans);
        }
    }

     

  • 相关阅读:
    数据库——表中显示乱码
    数据库字段类型
    HTML——动画效果:左侧固定悬浮栏(图标控制)
    HTML——动画效果:图片循环横向播放
    HTML——动画效果回到顶层(小火箭)
    HTML——图片自动轮换和手动轮换
    HTML——如何在html中插入视频
    HTML资料——做网页时遇到的
    JavaScrip——练习(做悬浮框再进一步:悬浮窗后缀悬浮窗——用this.className)
    ASP.NET MVC 4新建库项目中找不到 System.Web.Security 的引用
  • 原文地址:https://www.cnblogs.com/zxhl/p/5692688.html
Copyright © 2011-2022 走看看