基准时间限制:1 秒 空间限制:131072 KB 分值: 0
难度:基础题
收藏
关注
N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。
Input
第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000) 第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
Output
输出最小生成树的所有边的权值之和。
Input示例
9 14 1 2 4 2 3 8 3 4 7 4 5 9 5 6 10 6 7 2 7 8 1 8 9 7 2 8 11 3 9 2 7 9 6 3 6 4 4 6 14 1 8 8
Output示例
37
裸最小生成树
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <iomanip>
#include <math.h>
#include <map>
using namespace std;
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w",stdout);
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long LL;
typedef pair<int, int> PII;
using namespace std;
/*
* Kruskal算法求MST
*/
const int MAXN = 1000 + 5; //最大点数
const int MAXM = 50000 + 5; //最大边数
int F[MAXN];//并查集使用
struct Edge {
int u, v, w;
} edge[MAXM]; //存储边的信息,包括起点/终点/权值
int tol;//边数,加边前赋值为0
void addedge(int u, int v, int w) {
edge[tol].u = u;
edge[tol].v = v;
edge[tol++].w = w;
}
bool cmp(Edge a, Edge b) {
//排序函数,讲边按照权值从小到大排序
return a.w < b.w;
}
int find(int x) {
if(F[x] == -1)return x;
else return F[x] = find(F[x]);
}
int Kruskal(int n) { //传入点数,返回最小生成树的权值,如果不连通返回-1
memset(F, -1, sizeof(F));
sort(edge, edge + tol, cmp);
int cnt = 0; //计算加入的边数
int ans = 0;
for(int i = 0; i < tol; i++) {
int u = edge[i].u;
int v = edge[i].v;
int w = edge[i].w;
int t1 = find(u);
int t2 = find(v);
if(t1 != t2) {
ans += w;
F[t1] = t2;
cnt++;
}
if(cnt == n - 1)break;
}
if(cnt < n - 1)return -1; //不连通
else return ans;
}
int main() {
//FIN
int n, m;
while(~scanf("%d%d", &n, &m)) {
tol = 0;
for(int i = 1; i <= m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
}
int ans = Kruskal(n);
printf("%d\n", ans);
}
return 0;
}