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
代码如下:
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; }
相关文章推荐
- 解题报告:POJ1741 Tree 树上点分治(经典好题)
- Poj 1741 Tree 点分治 解题报告
- POJ 1741 Tree 解题报告(树分治)
- 深夜敲模板_3——树的点分治(poj1741解题报告)
- poj1741 Tree解题报告
- poj训练计划解题报告(做的不多,,,)
- Poj 2586 解题报告
- [zz]Flip and Shift -- POJ 1063 解题报告
- POJ - 3414 Pots解题报告(输出路径的bfs)
- 【原】 POJ 1035 Spell checker 编辑距离 解题报告
- 【原】 POJ 2155 Matrix 2D树状数组 解题报告
- 【原】 POJ 2739 Sum of Consecutive Prime Numbers 筛素数+积累数组 解题报告
- POJ 1002 解题报告
- poj 1118 2606解题报告
- poj1741 tree 点分治
- POJ 2942 Tarjan双联通分量+二分图 解题报告
- POJ 2390 解题报告
- POJ 1001 Exponentiation解题报告
- POJ 1011 Sticks 解题报告
- POJ 1274 解题报告