【树分治】 POJ 1741 Tree
来源:互联网 发布:艺人网络影响力榜2017 编辑:程序博客网 时间:2024/05/21 12:08
Tree
Time Limit: 1000MS Memory Limit: 30000KTotal Submissions: 17624 Accepted: 5757
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
这道题的题意大致是说有一棵n个点的树,要我们求树上距离小于k的点对的个数。
首先看数据范围,n<=10000,n^2的做法基本不用去想了。
然后,这是一棵树,那么对于任意一个节点,通过这条线的节点必然在点的两侧。
那么,每一次我们找到一个点,然后把通过这个点的所有直线找出来,那么之后这个点就可以无视掉,然后再在拆开的两棵子树中寻找一个点,以此类推。
在另一篇博客中咱介绍到了树的重心的内容,由树的重心的性质我们可知每次找重心可以达到最优的效果
然后我们找到重心之后,扫描点到其他点的连线长度。
求距离排序一遍O(nlogn)然后左右同时扫一遍O(n),容斥排掉两点在同一子树的情况即可。
代码如下:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int MAXN=20010;const int MAXM=10010;int n,m,ans;int u[MAXN],v[MAXN],w[MAXN],nex[MAXN];int fir[MAXM];bool vis[MAXM];int e_max;void add_edge(int a,int b,int c){ int e=e_max++; u[e]=a; v[e]=b; w[e]=c; nex[e]=fir[a]; fir[a]=e;}int subtree[MAXM];int maxtree[MAXM];int pt;void DfsSon(int x,int father){// cout<<x<<" "<<father<<endl;// system("pause"); subtree[x]=0; maxtree[x]=0; for(int e=fir[x];~e;e=nex[e]) { if(vis[v[e]] || v[e]==father) continue; DfsSon(v[e],x); subtree[x]+=subtree[v[e]]+1; maxtree[x]=max(maxtree[x],subtree[v[e]]+1); }}void DfsSize(int root,int x,int father){ maxtree[x]=max(maxtree[x],subtree[root]-subtree[x]); if(maxtree[pt]>maxtree[x]) { pt=x; } for(int e=fir[x];~e;e=nex[e]) { if(vis[v[e]] || v[e]==father) continue; DfsSize(root,v[e],x); }}int colle[MAXM],cont;void DfsColle(int x,int father,int lenth){ colle[cont++]=lenth; for(int e=fir[x];~e;e=nex[e]) { if(vis[v[e]] || father==v[e]) continue; DfsColle(v[e],x,lenth+w[e]); }}int calc(int x,int lenth){ int tmp=0; cont=0; //colle[cont++]=0; DfsColle(x,0,lenth); sort(colle,colle+cont);// cout<<"cont="<<cont;// for(int i=0;i<cont;i++) printf(",%d",colle[i]);// cout<<endl; int l=0,r=cont-1; while(l<r) { while(colle[l]+colle[r]>m && l<r) r--; tmp+=r-l; l++; } return tmp;}void Dfs(int x){ DfsSon(x,0); pt=x; DfsSize(x,x,0); //cout<<"pt="<<pt<<endl; ans+=calc(pt,0); vis[pt]=1; for(int e=fir[pt];~e;e=nex[e]) { if(vis[v[e]]) continue; ans-=calc(v[e],w[e]); Dfs(v[e]); }// cout<<ans<<endl;}int main(){ while(~scanf("%d%d",&n,&m) && n) { e_max=0; memset(fir,-1,sizeof fir); memset(vis,0,sizeof vis); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); add_edge(v,u,w); } ans=0; Dfs(1); printf("%d\n",ans); } return 0;}
0 0
- poj 1741 Tree 树分治
- poj 1741 Tree | 树分治
- poj 1741 Tree 树分治
- 【树分治】 POJ 1741 Tree
- 【POJ 1741】Tree(树分治)
- poj 1741 - Tree 树分治
- [POJ 1741]Tree[树分治]
- POJ 1741 Tree【树分治】
- 【树分治】 POJ 1741 Tree
- poj 1741 Tree(树分治)
- POJ 1741 Tree 树的分治
- poj 1741 Tree 树的分治
- poj 1741 Tree(树的分治)
- POJ 1741 Tree 树的点分治
- poj 1741 Tree 树的分治
- poj 1741 Tree 树的分治
- POJ 1741 Tree 树+点分治
- POJ - 1741 Tree 树的分治
- tjut 5410
- UVA10047The Monocycle
- 在libsvm中如何求最佳参数c和gamma
- 九宫格解锁
- Android第一个JNI程序
- 【树分治】 POJ 1741 Tree
- jQuery事件绑定.on()简要概述及应用
- Java实现——Dom4j读写XML文件
- Light OJ-----1336数论-----整数拆分推论
- MyBatis 批量插入数据
- 安装phantomjs,使用java代码进行截图
- FileOutputStream,OutputStreamWriter, BufferedWriter为什么连用?
- css空箭头的样式
- spring工程中得到注入bean的集中方式