1. 程式人生 > >牛客練習賽27-----C.水圖(DFS求最長路徑)

牛客練習賽27-----C.水圖(DFS求最長路徑)

題目描述: 小w不會離散數學,所以她van的圖論遊戲是送分的 小w有一張n個點n-1條邊的無向聯通圖,每個點編號為1~n,每條邊都有一個長度 小w現在在點x上 她想知道從點x出發經過每個點至少一次,最少需要走多少路 輸入描述: 第一行兩個整數 n,x,代表點數,和小w所處的位置 第二到第n行,每行三個整數 u,v,w,表示u和v之間有一條長為w的道路 輸出描述: 一個數表示答案 示例1 輸入 3 1 1 2 1 2 3 1 輸出 2 備註: 1 ≤ n ≤ 50000 , 1 ≤ w ≤ 2147483647

解題思路: 通過觀察(yy)發現,從xx 點出發,每條邊都走了兩遍,只有一條路徑走了一遍,那麼我們只需要找到一條最長的路徑,那麼就是總的邊權和減去最長路徑的邊權和就行了。現在問題就是找到權值最長的路徑,那麼我們就直接 v

ectorvector 建邊,然後 dfsdfs 找最長路徑即可。

程式碼如下:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vector>
using namespace std;
typedef long long LL;
const int MAXN = 50005;
struct Edge
{
    int nxt;
    LL w;
    Edge(int a, LL b)
    {
        nxt = a;
        w = b;
    }
};
vector<Edge> g[MAXN];
bool vis[MAXN];
LL sum = 0;
void dfs(int x, LL w)
{
    if(vis[g[x][0].nxt] && g[x].size()==1)//葉子節點且都已經訪問過節點
    {
        sum = max(sum, w);
        return ;
    }
    vis[x] = 1;
    for(int i=0; i<g[x].size(); i++) if(!vis[g[x][i].nxt]) dfs(g[x][i].nxt, w+g[x][i].w);
}
int main()
{
    int n, x; cin>>n>>x;
    LL ans = 0;
    for(int i=0; i<n-1; i++)
    {
        int u, v; LL w; cin>>u>>v>>w;
        g[u].push_back(Edge(v, w));
        g[v].push_back(Edge(u, w));
        ans += w;
    }
    sum = 0;
    dfs(x, 0);
    cout<<ans*2-sum<<endl;
    return 0;
}