hdu4514 湫湫系列故事——設計風景線

求樹的最長直徑,之前做過hdu2196,套用那道題的思路,兩次dfs,求出每個結點的最長直徑,然後找出最大的即爲整棵樹的最長直徑
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#define M 100010
#define ME 1000010
using namespace std;
struct node{
    int to,val,next;
}edge[ME*2];
int head[M];
int tot;
int n,m;
int len[M],len2[M],lenid[M];
bool vis[M];
int ans;
void insert(int u,int v,int val){
    edge[tot].to=v;
    edge[tot].val=val;
    edge[tot].next=head[u];
    head[u]=tot++;
}
bool dfs(int u,int pre){   //判環
    vis[u]=true;
    int i,v;
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].to;
        if(v==pre) continue;
        if(vis[v]||dfs(v,u)) return true;
    }
    return false;
}
void dfs1(int u,int pre){
    vis[u]=false;
    len[u]=len2[u]=0;
    int i,v;
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].to;
        if(v==pre) continue;
        dfs1(v,u);
        if(len[v]+edge[i].val>len[u]){
            len2[u]=len[u];
            len[u]=len[v]+edge[i].val;
            lenid[u]=v;
        }
        else if(len[v]+edge[i].val>len2[u]){
            len2[u]=len[v]+edge[i].val;
        }
    }
}
void dfs2(int u,int pre){
    int i,v;
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].to;
        if(v==pre) continue;
        if(lenid[u]==v){
            if(len2[u]+edge[i].val>len[v]){
                len2[v]=len[v];
                len[v]=len2[u]+edge[i].val;
                lenid[v]=u;
            }
            else if(len2[u]+edge[i].val>len2[v]){
                len2[v]=len2[u]+edge[i].val;
            }
        }
        else{
            if(len[u]+edge[i].val>len[v]){
                len2[v]=len[v];
                len[v]=len[u]+edge[i].val;
                lenid[v]=u;
            }
            else if(len[u]+edge[i].val>len2[v]){
                len2[v]=len[u]+edge[i].val;
            }
        }
        dfs2(v,u);
        ans=max(ans,len[v]);
    }
}
int main(){
    int i,u,v,val;
    while(scanf("%d%d",&n,&m)!=EOF){
        tot=0;
        memset(head,-1,sizeof(head));
        memset(vis,false,sizeof(vis));
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&val);
            insert(u,v,val);
            insert(v,u,val);
        }
        for(i=1;i<=n;i++)
            if(!vis[i])
                if(dfs(i,-1))
                    break;
        if(i<=n)
            printf("YES\n");
        else{
            ans=0;
            for(i=1;i<=n;i++)
                if(vis[i]){
                    dfs1(i,-1);
                    ans=max(ans,len[i]);
                    dfs2(i,-1);
                }
            printf("%d\n",ans);
        }
    }
    return 0;
}
還有一種更合適的方法,一次dfs即可求出一棵樹的最長直徑,len[i]表示以i爲根結點的樹的最長直徑,len2[i]表示以i爲根結點的樹且以i爲起點的最長直徑
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#define M 100010
#define ME 1000010
using namespace std;
struct node{
    int to,val,next;
}edge[ME*2];
int head[M];
int tot;
int n,m;
int len[M],len2[M];
bool vis[M];
int ans;
void insert(int u,int v,int val){
    edge[tot].to=v;
    edge[tot].val=val;
    edge[tot].next=head[u];
    head[u]=tot++;
}
bool dfs(int u,int pre){
    vis[u]=true;
    int i,v;
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].to;
        if(v==pre) continue;
        if(vis[v]||!dfs(v,u)) return false;
    }
    return true;
}
void dfs1(int u,int pre){
    vis[u]=false;
    len[u]=len2[u]=0;
    int i,v,temp;
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].to;
        if(v==pre) continue;
        dfs1(v,u);
        temp=len2[v]+edge[i].val+len2[u];
        if(temp>len[u])
            len[u]=temp;
        if(len2[v]+edge[i].val>len2[u])
            len2[u]=len2[v]+edge[i].val;
    }
    if(len[u]>ans)
        ans=len[u];
}
int main(){
    int i,u,v,val;
    while(scanf("%d%d",&n,&m)!=EOF){
        tot=0;
        bool end=false;
        memset(head,-1,sizeof(head));
        memset(vis,false,sizeof(vis));
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&val);
            insert(u,v,val);
            insert(v,u,val);
        }
        for(i=1;i<=n;i++)
            if(!vis[i])
                if(!dfs(i,-1))
                    break;
        if(i<=n)
            printf("YES\n");
        else{
            ans=0;
            for(i=1;i<=n;i++)
                if(vis[i])
                    dfs1(i,-1);
            printf("%d\n",ans);
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章