树分治基础模板以及树的重心(poj1741 tree)
来源:互联网 发布:mix2 知乎 编辑:程序博客网 时间:2024/06/05 03:48
好久没有更新博文了,这里更新一发~~
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.
InputDefine 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.
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.
OutputThe last test case is followed by two zeros.
For each test case output the answer on a single line.
Sample Input5 41 2 31 3 11 4 23 5 10 0Sample Output
8
简单翻译一下,给定你若干条边,然后让你求任意两点之间的距离小于等于k的有多少对,暴力n^2肯定要炸,于是我们就可以想到用树分治。
我们发现总共只有2种情况,经过根节点和不经过根节点。
设d[i]为i节点到根节点的距离(注意:根节点是会变动的,因为我们每一次都要求一次重心,为了不使树退化成一条链,于是根节点就是重心节点是变动的)
d[i]+d[j]<=k就是表示经过根节点,我们发现排序之后d[i]是有序的,于是我们用两个指针在序列中进行搜索就可以了这里复杂度为on
然后求剩下不经过根节点的情况的时候我们就在他自身的子节点中同样进行上述的操作就可以了,注意要求重心!!
然后综合一下,此题使用树的分治算法时间复杂度为O(nlog^2n) 。
接下来放上一份我抄过来的代码,明天应该还要再写一遍的~
这代码感觉思路比较的清晰,我做了一些改动。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define maxn 30000using namespace std;struct Node{int to,w;};int f[maxn],sum[maxn],d[maxn],book[maxn];int sz=0,k,n,root,ans=0;vector<int> dep;vector<Node> g[maxn];void getroot(int x,int fa){f[x]=0,sum[x]=1;for(int i=0;i<g[x].size();i++){int u=g[x][i].to;if(u!=fa&&!book[u]){getroot(u,x);sum[x]+=sum[u];f[x]=max(f[x],sum[u]);}}f[x]=max(f[x],sz-sum[x]);if(f[x]<f[root])root=x;}void getdep(int x,int fa){dep.push_back(d[x]);for(int i=0;i<g[x].size();i++){int u=g[x][i].to,w=g[x][i].w;if(u!=fa&&!book[u]){d[u]=d[x]+w;getdep(u,x);}}}int calc(int x,int init){dep.clear();d[x]=init;getdep(x,0);sort(dep.begin(),dep.end());int ans=0;for(int l=0,r=dep.size()-1;l<r;)if(dep[l]+dep[r]<=k) ans+=r-l,l++;else r--;return ans;}void work(int x){ans+=calc(x,0);book[x]=1;for(int i=0;i<g[x].size();i++){int u=g[x][i].to;if(!book[u]){ans-=calc(u,g[x][i].w);f[0]=sz=sum[u];getroot(u,root=0);work(root);}}}int main(){while(cin>>n>>k&&n&&k){memset(book,0,sizeof(book));for(int i=1;i<n;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);g[u].push_back((Node){v,w});g[v].push_back((Node){u,w});}f[0]=sz=n;getroot(1,root=0);ans=0;work(root);printf("%d\n",ans);for(int i=1;i<=n;i++) g[i].clear();}return 0;}
也就90行不算多~up++
阅读全文
0 0
- 树分治基础模板以及树的重心(poj1741 tree)
- POJ1741——Tree(树上分治,树的重心)
- POJ1741--Tree(树的分治)
- 【POJ1741】Tree 树分治 模板咯?
- POJ1741-树的分治&树的重心&树上的路径问题-Tree
- 【树分治】poj1741 Tree
- 【树分治】poj1741 tree
- 【POJ1741】Tree-树的点分治
- poj1741:Tree(点分治模板)
- poj1741树的分治
- 【树的点分治】【平衡树】[POJ1741]Tree
- [树的点分治] [POJ1741/POJ1987] Tree/Distance Statistics
- POJ 1741 Tree, 树的重心, 树分治, 点分治
- poj1741 树的点分治
- [POJ1741][JZOJ1166] 树中点对距离(点分治模板)
- POJ1741树的分治之点分治
- 深夜敲模板_3——树的点分治(poj1741解题报告)
- poj1741 Tree(点分治)
- trie树(uva11488)
- ac自动机基础模板(hdu2222)
- Linux SSH免密码登录错误
- 滚粗记
- 超智能体,tensorflow
- 树分治基础模板以及树的重心(poj1741 tree)
- 主席树(hdu2665)
- 数论学习(题库有很多啦。)
- 51nod 1242 斐波那契数列第N项
- 树链剖分基础模板(BZOJ1036[ZJOI2008]树的统计Count)
- 树链剖分模板题(luogu3384 【模板】树链剖分)
- Java源码阅读之ArrayList
- 建图最短路同余(luogu2662 vijos1054 xjoi2157)(bzoj2118)
- 左偏树