POJ1741 Tree
2016-07-04 20:01
302 查看
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
Source
LouTiancheng@POJ
树的重心:树上有一个结点,其所有的子树中最大的子树节点数最少,这个点就是这棵树的重心
点分治:先找出树的重心作为树根,统计其子树的答案,然后递归处理各子树,并去除重复算的答案。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const int mxn=30200; //base int n,k; int ans; //node struct edge{ int nx,to; int w; }e[40020]; int head[mxn],size[mxn],mc[mxn],dis[mxn];//邻接表队首 点的子树尺寸 点重量 结点深度 int cnt; //tree int root,mn=mxn; int tot; bool vis[mxn]; // void add_edge(int u,int v,int len){ e[++cnt]=(edge){head[u],v,len};head[u]=cnt; e[++cnt]=(edge){head[v],u,len};head[v]=cnt; } void dfssize(int u,int fa){//求结点子树尺寸 size[u]=1; mc[u]=0; for(int i=head[u];i;i=e[i].nx){ int v=e[i].to; if(v!=fa && !vis[v]){ dfssize(v,u); size[u]+=size[v]; mc[u]=size[v]>mc[u]? size[v]:mc[u]; } } return; } void findmc(int u,int fa,int rt){//求树的重心 mc[u]=max(mc[u],size[rt]-size[u]); if(mc[u]<mn){mn=mc[u];root=u;}//符合要求则更新树根 for(int i=head[u];i;i=e[i].nx){ int v=e[i].to; if(v!=fa && !vis[v])findmc(v,u,rt); } return; } void dist(int u,int fa,int d){//求u的子树的结点深度 dis[++tot]=d; for(int i=head[u];i;i=e[i].nx){ int v=e[i].to; if(v!=fa && !vis[v]) dist(v,u,d+e[i].w); } } int calc(int x,int d){//计算以x为中心,所有经过x的路径上符合要求的点对的数量 int res=0; tot=0; dist(x,0,d);//计算x为根的树的各结点深度 sort(dis+1,dis+tot+1);//深度由小到大排序 int l=1,r=tot; while(l<r){ while(dis[l]+dis[r]>k && l<r )r--;//两结点深度相加就是距离 res+=r-l; l++; } return res; } void dfs(int rt){//处理以rt为根的子树 // printf("test!: %d %d\n",rt,root); mn=n;//记得 dfssize(rt,0); findmc(rt,0,rt); ans+=calc(root,0);//在以rt为根的子树中找到重心后,以其为中心计算符合要求的点对数 vis[root]=1; for(int i=head[root];i;i=e[i].nx){ int v=e[i].to; if(!vis[v]){ ans-=calc(v,e[i].w);//减去以v为中心的答案数,避免之后计算重复 dfs(v); } } } int main(){ while(scanf("%d",&n) && n){ memset(vis,0,sizeof(vis)); memset(head,0,sizeof(head)); ans=0; cnt=0;//初始化!初始化! scanf("%d",&k); for(int i=1,u,v,d;i<n;i++){ scanf("%d%d%d",&u,&v,&d); add_edge(u,v,d); } dfs(1);//随便找个结点开始计算 printf("%d\n",ans); } return 0; }
相关文章推荐
- 根据网页宽度给BODY加不同的类名
- 解决Visual C++无法使用ActiveX 控件,Gallery目录下没有Registered ActiveX Controls问题
- 2.5 新建一个工程
- 如何配置网卡
- 移动元素
- 2.4 特殊功能寄存器和位定义
- HTML5+规范:Push(管理推送消息功能)
- [Spring框架]Spring AOP基础入门总结一.
- linux c程序中获取shell脚本输出的实现方法
- jmeter使用badboy录制脚本
- Anaconda Python 2.7 64-bit windows 安装中[Errno 9] Bad file descriptor解决方法
- 以架构的思维看世界
- 2.3 发光二极管(LED灯)
- 1.1 cacti 安装
- uva 11584 Partitioning by Palindromes dp(最少回文串划分)
- Redis 和 Memcached 的区别
- 在spark下用pyhton写worldCount
- HTML5+规范:Orientation(管理设备的方向信息)
- java7新特性之switch字符串比较原理
- 2.2 单片机最小系统