POJ 1741 Tree 树 点分治
2015-10-05 12:10
429 查看
题意:给定一颗n(n<=10000)个点的带权树,问这颗树中两点最短路小于等于K的点对有多少。
漆子超 的《分治算法在树的路径问题中的应用》中的例题之一。
因为是无根树,每次找树的重心,以重心转换为有根树,可以防止算法从O(NlogN)退化为O(n2),,然后求经过该点的最短路小于等于K的点对数。但是会算多,因此要减去算多的那些部分。。
代码:
漆子超 的《分治算法在树的路径问题中的应用》中的例题之一。
因为是无根树,每次找树的重心,以重心转换为有根树,可以防止算法从O(NlogN)退化为O(n2),,然后求经过该点的最短路小于等于K的点对数。但是会算多,因此要减去算多的那些部分。。
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long LL; const int MAXN=10000+100; struct Edge { int to,next,w; Edge(){} Edge(int _to,int _next,int _w):to(_to),next(_next),w(_w){} }e[MAXN<<1]; int head[MAXN],tot; void init(){ memset(head,-1,sizeof(head)); tot=0; } void AddEdge(int u,int v,int w){ e[tot]=Edge(v,head[u],w); head[u]=tot++; e[tot]=Edge(u,head[v],w); head[v]=tot++; } int n,K; int has[MAXN],root,siz[MAXN],ts[MAXN]; void getroot(int u,int fa){ siz[u]=1; ts[u]=0; for(int i=head[u];~i;i=e[i].next){ int v=e[i].to; if(has[v]||v==fa)continue; getroot(v,u); siz[u]+=siz[v]; ts[u]=max(ts[u],siz[v]); } ts[u]=max(ts[u],ts[0]-siz[u]); if(ts[u]<ts[root])root=u; } int dis[MAXN],res[MAXN]; void getdis(int u,int fa){ res[++res[0]]=dis[u]; siz[u]=1; for(int i=head[u];~i;i=e[i].next){ int v=e[i].to; if(has[v]||v==fa)continue; dis[v]=dis[u]+e[i].w; getdis(v,u); siz[u]+=siz[v]; } } int calc(int u,int init){ //printf("u:%d init:%d\n",u,init); dis[u]=init;res[0]=0;getdis(u,u); sort(res+1,res+1+res[0]); //for(int i=1;i<=res[0];i++)printf("%d ",res[i]); //puts(""); int l=1,r=res[0]; int ans=0; while(l<r){ if(res[l]+res[r]<=K)ans+=r-l++; else --r; } //printf("%d\n",ans); return ans; } int Ans; void dfs(int u){ Ans+=calc(u,0); has[u]=1; for(int i=head[u];~i;i=e[i].next){ int v=e[i].to; if(has[v])continue; //printf("%d-->%d %d\n",u,v,e[i].to); Ans-=calc(v,e[i].w); root=0;ts[0]=siz[v]; getroot(v,v); //printf("root:%d\n",root); dfs(root); } } int main(){ while(~scanf("%d%d",&n,&K)){ if(n+K==0)break; init(); memset(has,0,sizeof(has)); for(int i=0,x,y,w;i<n-1;i++){ scanf("%d%d%d",&x,&y,&w); AddEdge(x,y,w); } root=0;ts[0]=n; getroot(1,1); Ans=0; //printf("root:%d\n",root); dfs(root); printf("%d\n",Ans); } return 0; }
相关文章推荐
- C#实现获取系统目录并以Tree树叉显示的方法
- C语言实现输入一颗二元查找树并将该树转换为它的镜像
- 纯jsp打造无限层次的树代码
- php遍历树的常用方法汇总
- PHP树的深度编历生成迷宫及A*自动寻路算法实例分析
- PHP生成树的方法
- Java Swing中的表格(JTable)和树(JTree)组件使用实例
- python数据结构树和二叉树简介
- B+树到MySQL之innoDB
- ExtJS 4 树
- 数据库表TreeView树的快速生成
- Oracle 查询所有的父节点和子节点
- 树的双亲存储:
- 树
- 二叉树(2)——遍历的非递归实现
- 二叉树(2)——遍历的非递归实现
- 二叉树(3)——三叉链表示的二叉树
- C#实现树结构
- Java数据结构-二叉树及其遍历
- Android树状列表实现