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.
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.
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
- poj1741 Tree
- poj1741 Tree
- POJ1741 Tree
- 【poj1741】【Tree】
- [POJ1741]Tree
- POJ1741 Tree
- poj1741 Tree
- poj1741 Tree
- POJ1741 Tree
- 【poj1741】 Tree
- poj1741 Tree
- POJ1741 Tree.
- poj1741 Tree
- 【poj1741】Tree
- poj1741 Tree
- 【poj1741】Tree
- poj1741 Tree
- POJ1741-Tree
- 如何阅读源代码
- 如何为winform中的列表控件Combobox、ListBox控件绑定数据
- Cocos2d-x 学习随记二 Boost::Locale解决中文乱码问题
- github使用笔记
- 测试
- poj1741 Tree
- dlopen, cross call each other
- 2014辽宁省ACM程序设计大赛网络赛 问题 E: Help Your Teacher
- php 解压文件
- 3D数学读书笔记——多坐标系和向量基础
- Android自动化HTML报告
- 【读书笔记】学习OpenCV(中文版)第二章
- 【微软编程一小时】题目1 : Arithmetic Expression
- 命令行执行不回显不提示