题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz
输入输出格式
输入格式:第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)
接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi
输出格式:输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz
输入输出样例
说明
时空限制:1000ms,128M
数据规模:
对于20%的数据:N<=5,M<=20
扫描二维码关注公众号,回复:
1751977 查看本文章
对于40%的数据:N<=50,M<=2500
对于70%的数据:N<=500,M<=10000
对于100%的数据:N<=5000,M<=200000
样例解释:
所以最小生成树的总边权为2+2+3=7
#include<bits/stdc++.h> using namespace std; int n , m; const int MAXN = 400000 + 10; int g[5010] , First[MAXN], Next[MAXN], book[MAXN]; int ans; struct f { int u ; int v; int w; }a[MAXN]; int find(int x) { while(x != g[x]) x = g[x] = g[g[x]]; return x; } int com(const f &b, const f &c) { return b.w < c.w; } void kruskal() { int num = 0; sort(a + 1, a + 2*m + 1, com); for(int i = 1 ; i < m * 2; i ++ ) { int q1 = find(a[i].u) , q2 = find(a[i].v); if(q1 == q2) continue; ans += a[i].w; g[q2] = q1; num ++; if(num == n - 1) break; } } int main() { //int n , m cin >> n >> m; for(int i = 1; i <= n ; i ++) g[i] = i; for(int i = 1; i <= m ; i ++) { scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w); Next[i] = First[i]; First[i] = a[i].u; a[ i + m ].u = a[i].v; a[ i + m].v = a[i].u ; a[ i + m ].w = a[i].w; Next[ i + m ] = First[ i + m ]; First[ i + m ] = a[ i + m ].u; book[ a[i].u ] = 1;book[ a[i].v ] = 1; } for(int i = 1; i <= n ; i ++ ) if(book[i] == 0 ) { cout << "orz"; return 0; } kruskal(); printf("%d", ans); return 0; }