牛客練習賽27-----C.水圖(DFS求最長路徑)
阿新 • • 發佈:2018-12-11
題目描述: 小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)發現,從 點出發,每條邊都走了兩遍,只有一條路徑走了一遍,那麼我們只需要找到一條最長的路徑,那麼就是總的邊權和減去最長路徑的邊權和就行了。現在問題就是找到權值最長的路徑,那麼我們就直接 建邊,然後 找最長路徑即可。
程式碼如下:
#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; }