洛谷P3366 【模板】最小生成树(Kruskal)

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz

输入输出格式

输入格式:

第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

输出格式:

输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz

输入输出样例

输入样例#1: 
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1: 
7

说明

时空限制:1000ms,128M

数据规模:

对于20%的数据:N<=5,M<=20

对于40%的数据:N<=50,M<=2500

对于70%的数据:N<=500,M<=10000

对于100%的数据:N<=5000,M<=200000

Kruskal原理:将m条边按边权从小到大排序,枚举每条边,如果该边的起点和终点已经在最小生成树中,则跳过,否则就将这条边加入到最小生成树中。具体实现方面会借助于并查集,来判断两个点是否在最小生成树中(已连通)。

AC代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 int n,m;
 5 struct kkk{
 6     int qd,zd,len;
 7 }bian[200001];
 8 bool cmp(kkk a,kkk b) {//按照边权大小排序 
 9     return a.len < b.len;
10 } 
11 int f[5001];
12 int getf(int o) {//找父亲
13     if(o == f[o]) return o;
14     return f[o] = getf(f[o]);
15 }
16 int main(){
17     cin >> n >> m;
18     for(int i = 1;i <= m; i++) 
19         cin >> bian[i].qd >> bian[i].zd >> bian[i].len;
20     sort(bian+1,bian+m+1,cmp);
21     for(int i = 1;i <= n;i++)
22         f[i] = i;
23     int ans = 0;
24     for(int i = 1;i <= m; i++) {
25         int p1 = bian[i].qd;
26         int p2 = bian[i].zd;
27         int f1 = getf(p1);
28         int f2 = getf(p2);
29         if(f1 != f2) {//判断两个点是否在一个集合里 ,如果不在,就加上一条边 
30             ans += bian[i].len;
31             f[f1] = f2;
32         }
33     }
34     cout<<ans;
35     return 0;
36 } 

猜你喜欢

转载自www.cnblogs.com/lipeiyi520/p/10340376.html