zoukankan      html  css  js  c++  java
  • 牛客 旅行(并查集)

    传送门

    题目描述

    输入描述:

    第一行两个正整数 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;
    }
  • 相关阅读:
    【宋红康程序思想学习日记5】数组排序之冒泡法
    求割点 poj 1523
    网络流 poj 3308 最小割
    网络流最小割 POJ 3469
    网络流 POJ2112
    网络流 HDU 3605
    网络流HDU 2883
    网络流 最大流HDU 3549
    微信公众平台开发者中心服务器配置Token验证失败问题
    排列熵算法简介及c#实现
  • 原文地址:https://www.cnblogs.com/mohari/p/13654947.html
Copyright © 2011-2022 走看看