zoukankan      html  css  js  c++  java
  • Computer(hdu 2196)

    题意:给出一棵树,求出每个点与距离它最远的点的距离。

    /*
        树形DP 
        先把无根树转为有根树,对于一个节点i来说,与它相距最远的点有两种可能,一是在它的子树中,二是不在,我们分别用f[i][0]和f[i][1]来表示。
        f[i][0]很好求,从子节点向它的父亲递推就可以了。
        关键在于求f[i][1],我们发现f[i][1]可能有两种情况,一是来自它父亲的子树,而是来自它父亲的f[j][1],然后判断一下就好了。 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 10010
    #define lon long long
    using namespace std;
    int head[N],vis[N],n,cnt;
    lon f[N][2];
    struct node{int v,w,pre;}e[N*2];
    void add(int u,int v,int w){
        e[++cnt].v=v;e[cnt].w=w;e[cnt].pre=head[u];head[u]=cnt;
        e[++cnt].v=u;e[cnt].w=w;e[cnt].pre=head[v];head[v]=cnt;
    }
    lon dfs1(int u){
        vis[u]=1;
        for(int i=head[u];i;i=e[i].pre){
            if(vis[e[i].v]) continue;
            f[u][0]=max(f[u][0],dfs1(e[i].v)+e[i].w);
        }
        return f[u][0];
    }
    void dfs2(int u){
        vis[u]=1;
        lon max1=0,max2=0;int v1,v2;
        for(int i=head[u];i;i=e[i].pre){
            int v=e[i].v,w=e[i].w;
            if(vis[v]) continue;
            if(f[v][0]+w>max1){
                max2=max1;v2=v1;
                max1=f[v][0]+w;v1=v;
            }
            else if(f[v][0]+w>max2){
                max2=f[v][0]+w;v2=v;
            }
        }
        if(u!=1){
            if(f[u][1]>max1){
                max2=max1;v2=v1;
                max1=f[u][1];v1=-1;
            }
            else if(f[u][1]>max2){
                max2=f[u][1];v2=-1;
            }
        }
        for(int i=head[u];i;i=e[i].pre){
            int v=e[i].v;
            if(vis[v]) continue;
            if(v1!=v) f[v][1]=max1+e[i].w;
            else f[v][1]=max2+e[i].w;
            dfs2(e[i].v);
        }
    }
    void work(){
        for(int u=2;u<=n;u++){
            int v,w;scanf("%d%d",&v,&w);
            add(u,v,w);
        }
        memset(vis,0,sizeof(vis));
        dfs1(1);
        memset(vis,0,sizeof(vis));
        dfs2(1);
        for(int i=1;i<=n;i++)
            cout<<max(f[i][0],f[i][1])<<endl;
    }
    int main(){
        freopen("jh.in","r",stdin);
        while(scanf("%d",&n)!=EOF){
            memset(head,0,sizeof(head));
            memset(f,0,sizeof(f));
            cnt=0;
            work();
        }
        return 0;
    }
  • 相关阅读:
    [HEOI2015]兔子与樱花
    [HNOI2015]亚瑟王
    [JSOI2011]分特产
    某考试 T3 sine
    [JSOI2015]最小表示
    51NOD 1258 序列求和 V4
    Codeforces 622F The Sum of the k-th Powers
    Loj #6261. 一个人的高三楼
    [HAOI????] 硬币购物
    bzoj4318 OSU!
  • 原文地址:https://www.cnblogs.com/harden/p/6736254.html
Copyright © 2011-2022 走看看