OpenJudge 2631:Roads in the North(树的直径)

地址

树的直径:树的最长路.

显然若为无权值的无向图,树的直径就是边最多的一条路,若为有权无向图,树的直径就是权值总和最大的一条边

思路:遍历整棵树,从任意点出发,求出每个节点向下走的最大长度d1次大长度d2,则经过每个点的最长路为d1+d2,求出所有点最长路中的最大值即为直径

性质:一棵树中,一个点必然与直径的两个端点中的一个相距最远

#include <set>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <algorithm>
#include <stack>
using namespace std;
typedef long long ll;
const int N = 1e4 + 5;
const int inf = 0x3f3f3f3f;
const int M=N*2;
int h[N];
int e[M];
int w[M];
int ne[M];
int idx;
int ans=0;
void add(int a, int b,int c)
{    w[idx]=c;
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}
int dfs(int u,int father)
{
    int dist=0;//当前点往下走最大长度
    int d1=0,d2=0;//最大距离d1,次大距离d2;
    for(int i=h[u];~i;i=ne[i])
    {    int j=e[i];
        if(j==father)
        {
            continue;
        }
        int d=dfs(j,u)+w[i];
        dist=max(dist,d);
        if(d>d1)d2=d1,d1=d;
        else if(d>d2)
        {
            d2=d;
        }

    }
    ans=max(ans,d1+d2);
    return dist;
}


int main()
{
memset(h,-1,sizeof(h));
int n=0;
int a,b,c;
while(cin>>a>>b>>c)
{
    add(a,b,c);
    add(b,a,c);
}
dfs(1,-1);
cout<<ans<<endl;

    return 0;
}
View Code

 

posted @ 2021-02-04 23:44  blakee  阅读(70)  评论(0)    收藏  举报