Tree,点分治

Time Limit: 1 Sec  Memory Limit: 30 MB
Submit: 13  Solved: 9
[Submit][Status][Web Board]

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. 

给定一个带权树N个结点(1<=N<=10000),定义dist(u,v)为u,v两个点间的最 
短路径长度,路径长度定义为路径上所有边的权和。再给定一个K(1<=K<=10^9) 
如果对于不同的两个结点a,b.如果满足dist(a,b)<=K,则称其为合法点对,求 
有多少合法点对

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

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct my{
    int next,v,w;
};

inline int read()
{
    int p,data=0;
    char ch=0;
    while ((ch!='-') && ch<'0' || ch>'9') ch=getchar();
    if (ch=='-')
    {
        p=-1;
        ch=getchar();
    } else p=1;
    while (ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
    return data*p;
}

const int maxn=10000+10;

my bian[maxn*2];
int adj[maxn],fa,n,k,root=0,son[maxn],minn=(1<<30),dis[maxn*10],tot;
bool done[maxn];

inline void myinsert(int u,int v,int w){
     bian[++fa].v=v;
     bian[fa].w=w;
     bian[fa].next=adj[u];
     adj[u]=fa;
}

inline void dfs(int x,int fa){
    int pp=0;
    son[x]=1;
    for (int i=adj[x];i;i=bian[i].next){
        int v=bian[i].v;
        if(v==fa||done[v]) continue;
        dfs(v,x);
        son[x]+=son[v];
        pp=max(pp,son[v]);
    }
    pp=max(pp,n-son[x]);//ÁíÍâÒ»´ó¿ÅÊ÷
    if(pp<minn) {
            minn=pp,root=x;
    }
}

inline void dfs2(int x,int d,int fa){
     dis[++tot]=d;
     for (int i=adj[x];i;i=bian[i].next){
            int v=bian[i].v;
        if(!done[v]&&v!=fa){
            dfs2(v,d+bian[i].w,x);
        }
     }
}

inline int calc(int x,int d){
    tot=0;
    int ans=0;
    dfs2(x,d,0);
    sort(dis+1,dis+1+tot);
    int i=1,j=tot;
    for (;i<j;i++){
        while(dis[i]+dis[j]>k && i<j) j--;
        ans+=j-i;
    }
    return ans;
}

inline int work(int x){
    minn=(1<<30);
    dfs(x,0);
    done[root]=true;
    int ans=0;
    ans+=calc(root,0);
    for (int i=adj[root];i;i=bian[i].next){
            int v=bian[i].v;
        if(done[v]) continue;
        ans-=calc(v,bian[i].w);
        ans+=work(v);
    }
    return ans;
}

int main(){
    int u,v,w;
    while(scanf("%d%d",&n,&k)&&k+n){
            memset(bian,0,sizeof(bian));
            memset(adj,0,sizeof(adj));
            memset(done,false,sizeof(done));
            fa=0;
    for (int i=1;i<n;i++){
        u=read();
        v=read();
        w=read();
        myinsert(u,v,w);
        myinsert(v,u,w);
       }
       printf("%d\n",work(1));
    }
return 0;
}

猜你喜欢

转载自www.cnblogs.com/lmjer/p/9214403.html