链接:https://ac.nowcoder.com/acm/contest/547/E
来源:牛客网
题目描述
旅行商来到了一个新的国家,这个国家有N个城市,他们直接由N-1条道路相连接,每条道路的长度不尽相同
旅行商现在在1号城市,若他要每一个城市都游览一遍,他需要行走的最短路程是多少?
输入描述:
第一行一个数N (50000>N>1) 代表城市个数 之后N-1行 每行三个数x y z 代表从x到y的距离为z
输出描述:
输出最小距离
样例
输入
3 1 2 1 1 3 1
输出
3
题解
有n个点,n-1条边的无向连通图,所以这个图肯定没有环,可以看成以1为根节点的树。
最短的路程就是:权值之和最大的分支只走一次。其余的分支走一来回,每条边走了两次。
所以先把所有边的权值加起来乘2,再dfs找一下权值和最大分支,减一下就是答案。
dfs搜索权值和最大分支链的时候,每个点只遍历一次,所以不用标记数组记录是否走过,用个参数传递一下当前节点的父节点,不往父节点走就行了。
注意用链式前向星添加边的时候,是无向图,刚开始没注意到,只过了10%的数据,找了很长时间bug。
代码
#include<algorithm>
#include <iostream>
#include<cstring>
#include <cstdio>
using namespace std;
const int maxn=100005;
typedef long long ll;
int head[maxn];
int nex[maxn];
int to[maxn];
int w[maxn];
int cnt=0;
void add(int a,int b,int x){
to[cnt]=b;w[cnt]=x;nex[cnt]=head[a];head[a]=cnt++;
}
int dfs(int x,int father){
int y=0;
for(int i=head[x];i!=-1;i=nex[i]){
if(to[i]!=father) y=max(y,dfs(to[i],x)+w[i]);
}
return y;
}
int main(){
int n;
cin>>n;
memset(head,-1,sizeof(head));
int cnt=0;
for(int i=0;i<n-1;i++){
int a,b,x;
cin>>a>>b>>x;
add(a,b,x);
add(b,a,x);
cnt+=x;
}
cnt*=2;
cout<<cnt-dfs(1,-1)<<endl;
return 0;
}