牛客练习赛69 C.旅行

牛客练习赛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=2ndis(ai1,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=2ndis(ai1,ai)

示例1

输入

2 1
1 2 3

输出

3

这题明显的最大生成树,选 n n n 个结点和 n − 1 n-1 n1 条边,我比赛时一直没开大数组,吐了,套一个 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;
}

猜你喜欢

转载自blog.csdn.net/qq_43765333/article/details/108545265