您的位置:首页 > 其它

POJ 1741 树的点分治 解题报告

2017-07-17 21:01 323 查看
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

【解题报告】

可以看这个http://blog.csdn.net/onepointo/article/details/75221724

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define N 10010

int n,k,root,sum,ans;
struct Edge
{
int to,nxt,w;
}e[N<<2];
int cnt,head
,vis
,f
,son
,d
,dep
;

void adde(int u,int v,int w)
{
e[++cnt].w=w;
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
void getroot(int x,int fa)
{
son[x]=1;f[x]=0;
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=fa&&!vis[e[i].to])
{
getroot(e[i].to,x);
son[x]+=son[e[i].to];
f[x]=max(f[x],son[e[i].to]);
}
f[x]=max(f[x],sum-son[x]);
if(f[x]<f[root]) root=x;
}
void getdeep(int x,int fa)
{
dep[++dep[0]]=d[x];
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=fa&&!vis[e[i].to])
{
d[e[i].to]=d[x]+e[i].w;
getdeep(e[i].to,x);
}
}
int cal(int x,int v)
{
d[x]=v;dep[0]=0;
getdeep(x,0);
sort(dep+1,dep+dep[0]+1);
int l=1,r=dep[0],sum=0;
while(l<r)
{
if(dep[l]+dep[r]<=k) {sum+=r-l;l++;}
else r--;
}
return sum;
}
void solve(int x)
{
ans+=cal(x,0);
vis[x]=1;
for(int i=head[x];i;i=e[i].nxt)
{
if(vis[e[i].to]) continue;
ans-=cal(e[i].to,e[i].w);
sum=son[e[i].to];
root=0;
getroot(e[i].to,0);
solve(root);
}
}
int main()
{
while(scanf("%d%d",&n,&k)&&n+k)
{
ans=cnt=root=0;
memset(vis,0,sizeof(vis));
memset(head,0,sizeof(head));
for(int i=1;i<n;++i)
{
int u,v,w;scanf("%d%d%d",&u,&v,&w);
adde(u,v,w);adde(v,u,w);
}
f[0]=inf;sum=n;
getroot(1,0);
solve(root);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: