1. 程式人生 > 實用技巧 >牛客 旅行

牛客 旅行

題目描述

輸入描述:

第一行兩個正整數 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; }