小A與尤拉路(牛客-樹的直徑)

暱稱很長很長真是太好了發表於2020-11-10

題解:
尤拉路:從圖中任意一個點開始到圖中任意一個點結束的路徑,並且圖中每條邊只通過恰好一次

問你走完這樹上所有的點最短路徑是什麼。
因為樹是沒有環的,所以你走到葉子結點的時候需要往回走,也就是再走一遍剛剛走過的路。

所以我們確定一條主道路,遇到分支就走一遍(主道路是不需要走兩遍的)。
因為所有長度都是已知的,所以最短路徑也就是儘量讓這一條主路變長。
想一想最長的一條主路,那不就是樹的直徑嗎。
用所有路徑長度*2-樹的直徑即為答案。
兩次dfs求樹的直徑

/*Keep on going Never give up*/
//#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define int long long

#define endl '\n'
#define Accepted 0
#define AK main()
#define I_can signed
using namespace std;
const int maxn =2e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;

vector<pair<int,int> > edge[maxn];
int ans,sum,node;
bool visited[maxn];
void dfs(int x,int fa,int now){
    if(ans<now){
        ans=now;
        node=x;
    }
    for(auto i:edge[x]){
        int v=i.first;
        int w=i.second;
        if(v==fa) continue;
        if(!visited[v]){
            dfs(v,x,now+w);
        }
    }
}

signed main(){
    int n;
    cin>>n;
    for(int i=0;i<n-1;i++){
        int x,y,z;
        cin>>x>>y>>z;
        edge[x].push_back(make_pair(y,z));
        edge[y].push_back(make_pair(x,z));
        sum+=z*2;
    }
    dfs(1,-1,0);
    dfs(node,-1,0);
    cout<<sum-ans<<endl;
    return 0;
}

相關文章