牛客练习赛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
思路:
通过举例子我们可以看到,答案就是每条路径走了两遍,只有
一条边权和最大的路径只走了一遍,现在问题就是找到权值最长的路径,
那么我们就直接 建边,然后 dfs 找最长路径即可。
原文来自:https://blog.csdn.net/qingshui23/article/details/82843391
代码:
//dfs找到权值最大的路径即可 #include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 50005 int n,x; struct node { int to,cost; }; vector<node>a[maxn]; ll dfs(int x,int y)//x是终点,y是起点;目的是防止往回走 { ll mx=0; for(int i=0;i<a[x].size();i++) { int j=a[x][i].to; ll sum=0; if(j!=y) { sum+=a[x][i].cost; sum+=dfs(j,x); } mx=max(mx,sum); } return mx; } int main() { while(~scanf("%d %d",&n,&x)) { ll sum=0; for(int i=1;i<n;i++) { int u,v; ll c; scanf("%d %d %lld",&u,&v,&c); node tmp; tmp.to=v; tmp.cost=c; a[u].push_back(tmp); tmp.to=u; a[v].push_back(tmp); sum+=c*2; } ll ans=dfs(x,x); printf("%lld\n",sum-ans); } return 0; }