牛客 旅行(并查集)

传送门

题目描述

输入描述:

第一行两个正整数 n,m
接下来 m 行,每一行三个正整数 u,v,w 表示 u,v 之间有一条长度为 w 的边

输出描述:

示例1

输入

2 1
1 2 3

输出

3

说明

很显然,1,2 或者 2,1 都是合法的

备注:

题解:

题目要求构造一个连通图,使得其中的特定边权和最大。

特定边权和是即从a1到a2,a2到a3,直到an中所有路径中最短边之和。

这里的特定边权需要满足它是路径中最短的边,如果有多条可达路径,取其中所有路径中最大的最短边。

首先明确要边权和最大,所以大的边应该尽可能被利用,考虑贪心。

我们对边权进行降序排序,再使用并查集将点与点之间连通起来,使用并查集保证了取边是两点路径中的最小值。

因为其余点的连通对某一条边中的两点的路径构不成影响,由此我们尽可能的保证了边权和的最大, 又满足了

所取的边是dis要求的两点之间路径距离最小的边。

#include<bits/stdc++.h>
using namespace std;
const int N=500005;
int f[N];
struct node{
    int u,v,w;
}p[N];
void init(){
    for(int i=1;i<=N;i++){
        f[i]=i;
    }
}
int cmp(node a1,node a2){
    return a1.w>a2.w;
}
int find_(int a){
    if(f[a]==a)return a;
    else return f[a]=find_(f[a]);
}
int main(){
    init();
    int n,m;cin>>n>>m;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].w);
    }
    sort(p+1,p+1+m,cmp);
    long long ans=0;
    for(int i=1;i<=m;i++){
        int t1=find_(p[i].u);
        int t2=find_(p[i].v);
        if(t1==t2)continue;
        f[t1]=t2;
        ans+=p[i].w;
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/mohari/p/13654947.html