POJ 1741 Tree ——(树分治)
Posted Storm_Spirit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1741 Tree ——(树分治)相关的知识,希望对你有一定的参考价值。
思路参考于:http://blog.csdn.net/yang_7_46/article/details/9966455,不再赘述。
复杂度:找树的重心然后分治复杂度为logn,每次对距离数组dep排序复杂度为nlogn,而找重心的复杂度为dfs的复杂度——O(n),因此总的复杂度为O(nlognlogn)。
因为第一次写树分治,留个代码:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <vector> 5 using namespace std; 6 const int N = 10000 + 5; 7 8 struct edge 9 { 10 int v,w; 11 }; 12 int n,k,root,sz,ans; 13 bool vis[N]; 14 int son[N],f[N],d[N]; 15 vector<edge> G[N]; 16 vector<int> dep; 17 void init() 18 { 19 memset(vis,false,sizeof(vis)); 20 for(int i=1;i<=n;i++) G[i].clear(); 21 memset(son,0,sizeof son); 22 memset(f,0,sizeof f); 23 } 24 void addEdge(int u,int v,int w) 25 { 26 G[u].push_back((edge){v,w}); 27 G[v].push_back((edge){u,w}); 28 } 29 void getRoot(int u,int fa) 30 { 31 son[u] = 1; f[u] = 0; 32 for(int i=0;i<G[u].size();i++) 33 { 34 edge e = G[u][i]; 35 int v = e.v; 36 if(v == fa || vis[v]) continue; 37 getRoot(v,u); 38 son[u] += son[v]; 39 f[u] = max(f[u], son[v]); 40 } 41 f[u] = max(f[u], sz-son[u]); 42 if(f[u] < f[root]) root = u; 43 } 44 void getDep(int u,int fa) 45 { 46 dep.push_back(d[u]); 47 for(int i=0;i<G[u].size();i++) 48 { 49 edge e = G[u][i]; 50 int v = e.v, w= e.w; 51 if(v == fa || vis[v]) continue; 52 d[v] = d[u] + w; 53 getDep(v,u); 54 } 55 } 56 int cal(int u,int len) 57 { 58 dep.clear(); d[u] = len; 59 getDep(u, 0); 60 sort(dep.begin(), dep.end()); 61 int ret = 0; 62 for(int l=0,r=dep.size()-1;l<r;) 63 { 64 if(dep[l] + dep[r] <= k) ret += r - (l++); 65 else r--; 66 } 67 return ret; 68 } 69 void solve(int u) 70 { 71 ans += cal(u, 0); 72 vis[u] = 1; 73 for(int i=0;i<G[u].size();i++) 74 { 75 edge e = G[u][i]; 76 int v = e.v, w = e.w; 77 if(vis[v]) continue; 78 ans -= cal(v, w); 79 f[0] = sz = son[v]; 80 getRoot(v, root=0); 81 solve(root); 82 } 83 } 84 85 int main() 86 { 87 while(scanf("%d%d",&n,&k) == 2) 88 { 89 if(n == 0 && k == 0) break; 90 init(); 91 for(int i=1;i<=n-1;i++) 92 { 93 int u,v,w; 94 scanf("%d%d%d",&u,&v,&w); 95 addEdge(u,v,w); 96 } 97 f[0] = sz = n; 98 getRoot(1,root=0); 99 ans = 0; 100 solve(root); 101 printf("%d\n",ans); 102 } 103 return 0; 104 }
以上是关于POJ 1741 Tree ——(树分治)的主要内容,如果未能解决你的问题,请参考以下文章