题目描述
输入描述:
第一行两个正整数 n,m
接下来 m 行,每一行三个正整数 u,v,w 表示 u,v 之间有一条长度为 w 的边
输出描述:
示例1
输入
2 11 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; }