牛客练习赛69 C.旅行
题目描述
DK 有一个无向图 G,这个无向图有 n 个点 m 条边
你需要确定一个大小为 n 的排列 a,使 ∑ i = 2 n dis ( a i − 1 , a i ) \sum\limits_{i=2}^n \operatorname{dis}(a_{i-1},a_i) i=2∑ndis(ai−1,ai) 最大,求这个最大值 dis ( u , v ) \operatorname{dis}(u,v) dis(u,v) 表示从 u 到 v 的路径的中最短的边的边权,若有多条路径,则选令 dis ( u , v ) \operatorname{dis}(u,v) dis(u,v) 最大的路径
输入描述:
第一行两个正整数 n,m
接下来 m 行,每一行三个正整数 u,v,w 表示 u,v 之间有一条长度为 w 的边
输出描述:
仅一行,表示最大的 ∑ i = 2 n dis ( a i − 1 , a i ) \sum\limits_{i=2}^n \operatorname{dis}(a_{i-1},a_i) i=2∑ndis(ai−1,ai)
示例1
输入
2 1
1 2 3
输出
3
这题明显的最大生成树,选 n n n 个结点和 n − 1 n-1 n−1 条边,我比赛时一直没开大数组,吐了,套一个 kruskal 板子即可,AC代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
struct edge{
int u,v;
ll w;
}e[N];
int n,m,f[N];
bool cmp(edge a,edge b){
return a.w>b.w;
}
inline int findfather(int x){
return f[x]==x?x:f[x]=findfather(f[x]);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w;
sort(e+1,e+1+m,cmp);
ll ans=0;
for(int i=1;i<=m;i++){
int x=findfather(e[i].u),y=findfather(e[i].v);
if(x==y) continue;
f[x]=y;
ans+=e[i].w;
}
cout<<ans;
return 0;
}