题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz
输入输出格式
输入格式:
第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)
接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi
输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz
输入输出样例
说明
时空限制: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 }