poj1741 Tree

来源:互联网 发布:赢商网怎么样知乎 编辑:程序博客网 时间:2024/05/29 09:32
Tree
Time Limit: 1000MS Memory Limit: 30000KTotal Submissions: 9309 Accepted: 2780

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 41 2 31 3 11 4 23 5 10 0

Sample Output

8

Source

LouTiancheng@POJ

[Submit]   [Go Back]   [Status]   [Discuss]

Home Page   Go Back  To top

题目大意:

给定n,k,在有n个节点的树中,求路径长度不超过k的点对数。

输入格式:

第一行n,k

接下去n-1行u,v,e表示u和v之间有长度为e的连边

有多组数据,以0 0结尾

Solution:

          点分治模板题。先dfs或bfs O(n)找出树的重心,再O(n)求出各个点到该重心的路径长度,O(n log n)将距离排序,O(n)求出合法点对数(这里的想法是:若a数组单调递增,且有a[ l ]+a[r]<=k(l<r),l~r区间均可与l匹配,这样只需要每次l++,r不断递减统计就可以了,详见代码),接着遍历子树,统计出u到重心和v到重心的路径有重叠且和<=k的点对数,将其减去,递归求解即可。

Code:

常数有点渣

#include<cstdio>#include<cstring>#include<algorithm>#define CH getchar()#define inf 2147483647#define P [22222]using namespace std;int ans,n,k,u,v,e,tot,g P,pp P,ee P,he P,ne P,fa P,dis P,s P;bool vis P;inline void in(int &x){char ch;for(ch=CH;!(ch>=48 && ch<=57);ch=CH);for(x=0;ch>=48 && ch<=57;ch=CH)x=x*10+ch-48;}inline void pretr(){memset(he,0,sizeof he);memset(ee,0,sizeof ee);memset(pp,0,sizeof pp);memset(ne,0,sizeof ne);memset(vis,0,sizeof vis);tot=ans=0;}inline void add(int u,int v,int e){ee[++tot]=e;pp[tot]=v;ne[tot]=he[u];he[u]=tot;}inline int O_O(int u){int l;g[*g=l=1]=u;fa[u]=0;for(;l<=*g;++l)for(int e=he[g[l]];e;e=ne[e])if(!vis[pp[e]] && fa[g[l]]^pp[e]){g[++*g]=pp[e];fa[pp[e]]=g[l];}for(l--;l;--l){int v=g[l];s[v]=1;for(int e=he[v];e;e=ne[e])if(!vis[pp[e]] && pp[e]^fa[v])s[v]+=s[pp[e]];}int MN=inf,an;for(l=1;l<=*g;++l){int k=g[l],MX=*g-s[k];for(int e=he[k];e;e=ne[e])if(!vis[pp[e]] && pp[e]^fa[k] && s[pp[e]]>MX)MX=s[pp[e]];if(MX<MN)MN=MX,an=k;}return an;}inline int deal(int u,int QwQ){int l,r,an=0;g[*g=l=1]=u;fa[u]=0;dis[1]=QwQ;for(;l<=*g;++l)for(int e=he[g[l]];e;e=ne[e])if(!vis[pp[e]] && pp[e]^fa[g[l]]){g[++*g]=pp[e];fa[pp[e]]=g[l];dis[*g]=ee[e]+dis[l];}sort(dis+1,dis+1+*g);for(l=1,r=*g;l<r;++l){while(dis[r]+dis[l]>k && l<r)r--;an+=r-l;}return an;}void solve(int u){int root=O_O(u);vis[root]=true;ans+=deal(root,0);for(int e=he[root];e;e=ne[e])if(!vis[pp[e]])ans-=deal(pp[e],ee[e]);for(int e=he[root];e;e=ne[e])if(!vis[pp[e]])solve(pp[e]);}int main(){while(true){in(n);in(k);if(!n)return 0;pretr();for(int i=1;i<n;++i){in(u);in(v);in(e);add(u,v,e);add(v,u,e);}solve(1);printf("%d\n",ans);}}


0 0
原创粉丝点击