zoukankan      html  css  js  c++  java
  • [hdu2196]Computer树的直径

    题意:求树中距离每个节点的最大距离。

    解题关键:两次dfs,第一次从下向上dp求出每个节点子树中距离其的最大距离和不在经过最大距离上的子节点上的次大距离(后序遍历),第二次从上而下dp求出其从父节点过来的最大距离(先序遍历).

    如果vi不是u最长距离经过的节点,$d[{v_i}][2] = dist[{v_i}][u] + max (d[u][0],d[u][2])$;
    如果vi是u最长距离经过的节点,$d[{v_i}][2] = dist[{v_i}][u] + max (d[u][1],d[u][2]);$

    最终答案即是从下而来和从上而来的距离的最大值。

     取最大值和次大值时的>=和>是无所谓的,都可以过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=1e5+2;
     5 int head[maxn],tot,d[maxn][3],longest[maxn];
     6 struct edge{
     7     int to;
     8     int nxt;
     9     int w;
    10 }e[maxn<<1];
    11 void add_edge(int u,int v,int w){
    12     e[tot].to=v;
    13     e[tot].w=w;
    14     e[tot].nxt=head[u];
    15     head[u]=tot++;
    16 }
    17 
    18 int dfs1(int u,int fa){//返回子树最大距离 
    19     for(int i=head[u];i!=-1;i=e[i].nxt){
    20         int v=e[i].to;
    21         if(v==fa) continue;
    22         int tmp=dfs1(v,u);
    23         if(d[u][0]<tmp+e[i].w){
    24             longest[u]=v;
    25             d[u][1]=d[u][0];
    26             d[u][0]=tmp+e[i].w;
    27         }else if(d[u][1]<tmp+e[i].w){//求次大距离必须加else if 
    28             d[u][1]=tmp+e[i].w;
    29         }
    30     }
    31     return d[u][0];
    32 }
    33 
    34 void dfs2(int u,int fa){
    35     for(int i=head[u];i!=-1;i=e[i].nxt){
    36         int v=e[i].to;
    37         if(v==fa) continue;
    38         if(v==longest[u]) d[v][2]=max(d[u][1],d[u][2])+e[i].w;
    39         else d[v][2]=max(d[u][0],d[u][2])+e[i].w;
    40         dfs2(v,u);
    41     }
    42 } 
    43 
    44 
    45 int main(){
    46     int n;
    47     ios::sync_with_stdio(0);
    48     cin.tie(0);
    49     cout.tie(0);
    50     while(cin>>n){
    51         tot=0;
    52         memset(d,0,sizeof d);
    53         memset(head,-1,sizeof head);
    54         memset(longest,0,sizeof longest);
    55         int a,b;
    56         for(int i=2;i<=n;i++){
    57             cin>>a>>b;
    58             add_edge(i,a,b);
    59             add_edge(a,i,b);
    60         }
    61         dfs1(1,-1);
    62         dfs2(1,-1);
    63         for(int i=1;i<=n;i++){
    64             cout<<max(d[i][0],d[i][2])<<"
    ";
    65         }
    66     }
    67     return 0;
    68 }

     最优写法:

    不需要记录longest,只要d[v][0]+e[i].w==d[u][0],此时即可取次大距离。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=1e5+2;
     5 int head[maxn],tot,d[maxn][3];
     6 struct edge{
     7     int to;
     8     int nxt;
     9     int w;
    10 }e[maxn<<1];
    11 void add_edge(int u,int v,int w){
    12     e[tot].to=v;
    13     e[tot].w=w;
    14     e[tot].nxt=head[u];
    15     head[u]=tot++;
    16 }
    17 
    18 void dfs1(int u,int fa){//返回子树最大距离 
    19     for(int i=head[u];i!=-1;i=e[i].nxt){
    20         int v=e[i].to;
    21         if(v==fa) continue;
    22         dfs1(v,u);
    23         int tmp=d[v][0]+e[i].w;
    24         if(d[u][0]<=tmp){
    25             d[u][1]=d[u][0];
    26             d[u][0]=tmp;
    27         }else if(d[u][1]<tmp){//求次大距离必须加else if 
    28             d[u][1]=tmp;
    29         }
    30     }
    31 }
    32 
    33 void dfs2(int u,int fa){
    34     for(int i=head[u];i!=-1;i=e[i].nxt){
    35         int v=e[i].to;
    36         if(v==fa) continue;
    37         if(d[u][0]==d[v][0]+e[i].w) d[v][2]=max(d[u][1],d[u][2])+e[i].w;
    38         else d[v][2]=max(d[u][0],d[u][2])+e[i].w;
    39         dfs2(v,u);
    40     }
    41 } 
    42 
    43 
    44 int main(){
    45     int n;
    46     ios::sync_with_stdio(0);
    47     cin.tie(0);
    48     cout.tie(0);
    49     while(cin>>n){
    50         tot=0;
    51         memset(d,0,sizeof d);
    52         memset(head,-1,sizeof head);
    53         int a,b;
    54         for(int i=2;i<=n;i++){
    55             cin>>a>>b;
    56             add_edge(i,a,b);
    57             add_edge(a,i,b);
    58         }
    59         dfs1(1,-1);
    60         dfs2(1,-1);
    61         for(int i=1;i<=n;i++){
    62             cout<<max(d[i][0],d[i][2])<<"
    ";
    63         }
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    计算器部分代码
    学写压缩壳心得系列之二 掌握PE结构 ,曲径通幽
    headerfiles
    VC实现文件拖拽
    学写压缩壳心得系列之三 模拟加载,步步为营
    ASPack 2.x (without poly) > Alexey Solodovnikov [Overlay]脱壳
    学写压缩壳心得系列之一 熟悉概念,未雨绸缪
    upx最新壳脱壳测试
    正则表达式大全
    win7 iis http 500 错误
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7418815.html
Copyright © 2011-2022 走看看