牛客练习赛27-----C.水图(DFS求最长路径)

版权声明:编写不易,转载请注明出处,谢谢。 https://blog.csdn.net/qingshui23/article/details/82843391

传送门
链接:https://www.nowcoder.com/acm/contest/188/C
来源:牛客网

题目描述:
小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)发现,从 x x 点出发,每条边都走了两遍,只有一条路径走了一遍,那么我们只需要找到一条最长的路径,那么就是总的边权和减去最长路径的边权和就行了。现在问题就是找到权值最长的路径,那么我们就直接 v e c t o r vector 建边,然后 d f s dfs 找最长路径即可。

代码如下:

#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;
}

猜你喜欢

转载自blog.csdn.net/qingshui23/article/details/82843391
今日推荐