poj2114(树的点分治)

来源:互联网 发布:当代文学论文选题知乎 编辑:程序博客网 时间:2024/06/05 23:03

    参考文章: http://blog.csdn.net/yang_7_46/article/details/9966455

  

   题目的大致意思是要求出是否存在两点间的路径长度为K的情况

  不知道为什么1741一直是re,主要还是看别人文章学习来的树的点分治。

  

  点分治,主要是分类来进行处理,对于两点之前求距离可以分为两类情况:

  1.过根节点(不在一棵子树内)

  2.不过根节点(在同一棵子树内)


  第2种情况可以通过递归转化成第1种情况,对于第1种情况,求出到根节点的距离dis,然后它们之前的距离就为dis[i] + dis[j],对于求满足的情况,有个比较巧妙的办法,就是对其排序之后,然后在O(n)的时间内找到,主要还是在对1741的时候作用比较大(1741是要求距离小于等于K,2114是要求刚好等于K)


  另外对于树而言,要求其重心(树的最大深度的值最小),这样在计算的时候可以避免出现类似一条链的情况。 

//得到重心void getRoot(int now, int fa){//s代表树中点的个数,f代表它的深度s[now] = 1; f[now] = 0;for(int k = head[now]; k != -1; k = edge[k].next){//如果访问过,或者是其父节点if( fa == edge[k].t || visit[edge[k].t]) continue;getRoot(edge[k].t, now);s[now] += s[edge[k].t];f[now] = max(f[now], s[edge[k].t]);}f[now] = max(f[now], size - s[now]);if( f[now] < f[root] )root = now;}
<pre name="code" class="cpp">//得到距离根的距离void getD(int now, int fa){dep.push_back(d[now]);s[now] = 1;for(int k = head[now]; k != -1; k = edge[k].next){if( edge[k].t == fa || visit[edge[k].t] ) continue;d[edge[k].t] = d[now] + edge[k].w;getD(edge[k].t, now);s[now] += s[edge[k].t];}}//计算个数int calc(int now, int dis){dep.clear();d[now] = dis;getD(now,0);sort(dep.begin(), dep.end());int ret = 0, l = 0, r = dep.size() - 1;while( l < r ){if (dep[l] + dep[r] == K) {  if (dep[l] == dep[r]) {  ret += (r-l+1)*(r-l)/2; break;  }  int i=l, j=r;  while (dep[i] == dep[l]) i++;  while (dep[j] == dep[r]) j--;  ret += (i-l)*(r-j);  l = i, r = j;  } else if (dep[l] + dep[r] < K) l++;  else r--; }return ret;}void work(int temp){ans += calc(temp,0);visit[temp] = true;for(int k = head[temp]; k != -1; k = edge[k].next){if( visit[edge[k].t] ) continue;ans -= calc(edge[k].t, edge[k].w);f[0] = size = s[edge[k].t];getRoot(edge[k].t, root = 0);work(root);}}void solve(){Mem(head, -1);int u,w;kNum = 0;for(int i = 1; i <= n; i ++){while(cin>>u && u){cin>>w;addEdge(i, u, w);addEdge(u, i, w);}}while(cin>>K && K){Mem(visit,false);f[0] = size = n;getRoot(1, root = 0);ans = 0;work(root);printf("%s\n",ans > 0 ? "AYE" : "NAY" );}printf(".\n");}





  

0 0