XTU OJ Highway(樹的直徑)

樹的直徑是指樹的最長簡單路。
求法: 兩遍DFS :先任選一個起點DFS找到最長路的終點,再從終點進行DFS,則第二次DFS找到的最長路即爲樹的直徑;
原理: 設起點爲u,第一次DFS找到的終點v一定是樹的直徑的一個端點
證明:
1) 如果u 是直徑上的點,則v顯然是直徑的終點(因爲如果v不是的話,則必定存在另一個點w使得u到w的距離更長,則於DFS找到了v矛盾)
2) 如果u不是直徑上的點,則u到v必然於樹的直徑相交(反證),那麼交點到v 必然就是直徑的後半段了,所以v一定是直徑的一個端點,所以從v進行DFS得到的一定是直徑長度

這題的解法就是通過第一次DFS找到樹的直徑的一個端點Start,然後從Start開始用一次DFS找到直徑上的另一個端點End(算出每個點到Start的距離),最後再從End開始DFS一次(算出每個點到End的距離),最後求解的就是所有點到直徑端點的最大距離的和再減去一個直徑的距離(因爲直徑累加了兩次,所以要減去一次)

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <memory>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <climits>
#include <cstring>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <functional>

//#define FIN freopen("input.txt","r",stdin);
//#define FOUT freopen("output.txt","w+",stdout);
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps=1e-8;
const double Pi=acos(-1.0);
const int N=100100;

struct Edge
{
    int to,w;
};
vector<Edge> G[N];
bool vis[N];
int n,Start,End;
ll dis1[N],dis2[N],d[N],maxcost;
void dfs(int u)
{
    vis[u] = 1;
    int size = G[u].size();     //與頂點u相連的點數
    for (int i = 0; i<size; i++)             //對與頂點u相連的點數進行掃描
    {
        int v = G[u][i].to;
        if (!vis[v])
        {
            d[v] = d[u] + G[u][i].w;
            dfs(v);
        }
    }
}
void init()
{
        memset(vis,0,sizeof(vis));
        memset(d,0,sizeof(d));
}
int main()
{
    while(~scanf("%d",&n))
    {
        memset(dis1,0,sizeof(dis1));
        memset(dis2,0,sizeof(dis2));
        for(int i=0; i<N; i++)
            G[i].clear();
        int from,to,cost;
        for(int i=0; i<n-1; i++)
        {
            scanf("%d %d %d",&from,&to,&cost);
            G[from].push_back((Edge){to,cost});
            G[to].push_back((Edge){from,cost});
        }
        init();
        dfs(1);
        maxcost=-1;
        for(int i=1;i<=n;i++)
        {
            if(d[i]!=0&&maxcost<d[i])
            {
                maxcost=d[i];
                Start=i;
            }
        }
        init();
        dfs(Start);
        maxcost=-1;
        for(int i=1;i<=n;i++)
        {
            dis1[i]=d[i];
            if(d[i]!=0&&maxcost<d[i])
            {
                End=i;
                maxcost=d[i];
            }
        }
        init();
        dfs(End);
        memcpy(dis2,d,sizeof(d));
//        for(int i=1;i<=n;i++)
//            printf("%d ",dis1[i]);
//        cout<<endl;
//        for(int i=1;i<=n;i++)
//            printf("%d ",dis2[i]);
//        cout<<endl;
//        cout<<maxcost<<endl;
        ll ans=0;
        for(int i=1;i<=n;i++)
            ans+=max(dis1[i],dis2[i]);
        printf("%I64d\n",ans-maxcost);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章