• LightOJ1257 Farthest Nodes in a Tree (II)(树的点分治)


    题目给一棵树,边带有权值,求每一点到其他点路径上的最大权和。

    树上任意两点的路径都可以看成是经过某棵子树根的路径,即路径权=两个点到根路径权的和,于是果断树分治。

    对于每次分治的子树,计算其所有结点到根的距离;对于每个结点,找到另一个离根最远的且与该结点路径过根的结点,二者的距离和就是这个点在过这棵子树的根能到的最远距离。

    现在问题就是怎么比较快地找到这另一个最远距离的点。。两点路径过根,说明两点间不存在一点是另一点的祖先。。我一开始还想用DFS序+线段树来着。。想了想,想出了线性的算法:

    记录每个结点属于根的哪个儿子,把当前分治子树的所有结点以属于根的哪个儿子分组,对于每个结点对应过根的结点就不能在同一组要到别的组找,而且肯定是某个组里面根距离最大的值的那个结点。通过计算每个组里面结点到根的最大值作为组的值,以及这些组的最大值和次大值,就OK了。

    好难描述= =反正这样这题就用树分治解决了,时间复杂度O(nlogn)。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm> 
      4 using namespace std;
      5 #define INF (1<<29)
      6 #define MAXN 33333
      7 struct Edge{
      8     int u,v,w,next;
      9 }edge[MAXN<<1];
     10 int NE,head[MAXN];
     11 void addEdge(int u,int v,int w){
     12     edge[NE].u=u; edge[NE].v=v; edge[NE].w=w;
     13     edge[NE].next=head[u]; head[u]=NE++;
     14 }
     15 
     16 bool vis[MAXN];
     17 
     18 int size[MAXN];
     19 void getSize(int u,int fa){
     20     size[u]=1;
     21     for(int i=head[u]; i!=-1; i=edge[i].next){
     22         int v=edge[i].v;
     23         if(vis[v] || v==fa) continue;
     24         getSize(v,u);
     25         size[u]+=size[v];
     26     }
     27 }
     28 int centre,mini;
     29 void getCentre(int u,int fa,int &tot){
     30     int res=tot-size[u];
     31     for(int i=head[u]; i!=-1; i=edge[i].next){
     32         int v=edge[i].v;
     33         if(vis[v] || v==fa) continue;
     34         getCentre(v,u,tot);
     35         res=max(res,size[v]);
     36     }
     37     if(mini>res){
     38         mini=res;
     39         centre=u;
     40     }
     41 }
     42 int getCentre(int u){
     43     getSize(u,u);
     44     mini=INF;
     45     getCentre(u,u,size[u]);
     46     return centre;
     47 }
     48 
     49 int n,ans[MAXN];
     50 int dn,dx[MAXN],dy[MAXN],mx1,mx2,belong[MAXN],mx[MAXN];
     51 void dfs(int u,int fa,int dist,int &gp){
     52     dx[dn]=u; dy[dn]=dist; dn++;
     53     belong[u]=gp;
     54     mx[gp]=max(mx[gp],dist);
     55     for(int i=head[u]; i!=-1; i=edge[i].next){
     56         int v=edge[i].v;
     57         if(vis[v] || v==fa) continue;
     58         dfs(v,u,dist+edge[i].w,gp);
     59     }
     60 }
     61 void conquer(int u){
     62     dn=0; mx1=0; mx2=-INF;
     63     dx[dn]=u; dy[dn]=0; dn++;
     64     belong[u]=u;
     65     for(int i=head[u]; i!=-1; i=edge[i].next){
     66         int v=edge[i].v;
     67         if(vis[v]) continue;
     68         mx[v]=-INF;
     69         dfs(v,u,edge[i].w,v);
     70         if(mx1<mx[v]) mx2=mx1,mx1=mx[v];
     71         else if(mx2<mx[v]) mx2=mx[v];
     72     }
     73     for(int i=0; i<dn; ++i){
     74         if(mx[belong[dx[i]]]!=mx1) ans[dx[i]]=max(ans[dx[i]],dy[i]+mx1);
     75         else ans[dx[i]]=max(ans[dx[i]],dy[i]+mx2);
     76     }
     77 }
     78 
     79 void divide(int u){
     80     u=getCentre(u);
     81     vis[u]=1;
     82     conquer(u);
     83     for(int i=head[u]; i!=-1; i=edge[i].next){
     84         int v=edge[i].v;
     85         if(vis[v]) continue;
     86         divide(v);
     87     }
     88 }
     89 int main(){
     90     int t,a,b,c;
     91     scanf("%d",&t);
     92     for(int cse=1; cse<=t; ++cse){
     93         NE=0;
     94         memset(head,-1,sizeof(head));
     95         scanf("%d",&n);
     96         for(int i=1; i<n; ++i){
     97             scanf("%d%d%d",&a,&b,&c);
     98             addEdge(a,b,c); addEdge(b,a,c);
     99         }
    100         memset(vis,0,sizeof(vis));
    101         for(int i=0; i<n; ++i) ans[i]=-INF;
    102         divide(0);
    103         printf("Case %d:
    ",cse);
    104         for(int i=0; i<n; ++i) printf("%d
    ",ans[i]);
    105     }
    106     return 0;
    107 }
  • 相关阅读:
    设计模式
    设计模式
    设计模式
    设计模式
    【Sublime】许可证 及 相关设置
    【Linux】跳过ubuntu grub2引导,使用Windows引导ubuntu
    【Linux】Windows 7下硬盘安装Ubuntu 14.10图文教程
    【ACM】连连看 hdu1175
    【算法】约瑟夫环 C++源代码
    【Java】配置JAVA的环境变量
  • 原文地址:https://www.cnblogs.com/WABoss/p/5246217.html
Copyright © 2020-2023  润新知