您的位置:首页 > 其它

POJ 1741Tree(树分治)

2015-12-22 19:09 274 查看
Tree

Time Limit: 1000MSMemory Limit: 30000K
Total Submissions: 15035Accepted: 4902
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

解题思路:
树分治:就是将一棵树以重心分成若干个树。然后分2种情况,一种是包括根,另一种是不包括根。 对于不包括的就可以进行分治。而对于包括的就先统计每个点(当前树的点)到root的距离,利用单调性,求出两两可以配对的,不过如果两个点在同一棵子树上时就要减掉,因为在接下去的分治中,它会被统计,所以为了避免统计,要减掉。对于不要的点对可以分别统计每棵子树包括的对数。

#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

using namespace std;

int n,m,opp;

long long sum=0;

int len=0;

struct data

{

int from,to,zhi,next;

}e[91009];

int h[11001];

int son[11001];

bool vis[11001];

int ma,root,ge;

int lg[11001];

void insert(int x,int y,int length){++len; e[len].from=x; e[len].to=y; e[len].zhi=length; e[len].next=h[x]; h[x]=len;}

int getroot(int o,int fa)

{

son[o]=1;

int u=h[o];

while (u!=0)

{

if (e[u].to!=fa && vis[e[u].to])

{

son[o]+=getroot(e[u].to,o);

}

u=e[u].next;

}

int zan=max(son[o]-1,opp-son[o]);

if (zan<ma){ma=zan;root=o;}

return son[o];

}

int getdeep(int now,int leng,int fa)

{

++ge;

lg[ge]=leng;

int u=h[now];

while (u!=0)

{

if (vis[e[u].to] && e[u].to!=fa)

{

getdeep(e[u].to,leng+e[u].zhi,now);

}

u=e[u].next;

}

}

int cal()

{

int t=0;

for (int l=1,r=ge;l<r;)

{

if (lg[l]+lg[r]<=m)

{

t+=r-l;++l;

}else

--r;

}

return t;

}

int work(int ro)

{

vis[ro]=false; ge=0;

getdeep(ro,0,0);

sort(lg+1,lg+ge+1);

sum+=cal();

int u=h[ro];

while (u!=0)

{

if (vis[e[u].to])

{

ge=0; getdeep(e[u].to,e[u].zhi,0);

sort(lg+1,lg+ge+1);

sum-=cal();

ma=0x7fffffff;

opp=son[e[u].to];

getroot(e[u].to,ro); work(root);

}

u=e[u].next;

}

}

int main()

{

while (scanf("%d %d",&n,&m) && n!=0 )

{

memset(h,0,sizeof(h)); len=0;

for (int i=1;i<=n-1;++i)

{

int x,y,length;

scanf("%d %d %d",&x,&y,&length);

insert(x,y,length); insert(y,x,length);

}

sum=0; ma=0x7fffffff; root=0; opp=n;

memset(vis,true,sizeof(vis));

getroot(1,0);

work(root);

cout<<sum<<endl;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: