标签:
第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)
输出最小生成树的所有边的权值之和。
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
37
---------------------------------------------------------------我是分割线^_^-----------------------------------------------------------
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1005;
const int MAXM = 50005;
int cost[MAXN][MAXN];
struct Edge
{
int s, t, d; // s为起点,t为终点,d为权值
} edge[MAXM];
/**
* prim算法
* @param cost: 赋权邻接矩阵
* @param n: 节点的编号,为1-n
*/
int prim(int cost[][MAXN], int n)
{
int rst = 0;
bool vis[MAXN]; // 标记节点是否被加入
int label[MAXN]; // 选择节点的依据
memset(vis, false, sizeof(vis));
vis[1] = true; // 从任意一个节点开始
for (int i = 1; i <= n; ++i) {
label[i] = cost[1][i];
}
for (int times = 1; times <= n - 1; ++times) { // 循环n - 1次,每次加入一个节点
int minEdge = INF;
int choosed = -1;
for (int i = 1; i <= n; ++i) { //选择可扩张边上的节点
if (!vis[i] && label[i] < minEdge) {
minEdge = label[i];
choosed = i;
}
}
if (minEdge == INF) { // mincost没更新,说明原图没有联通
return -1;
}
rst += minEdge;
vis[choosed] = true;
for (int i = 1; i <= n; ++i) { // 更新节点的标记值
if (!vis[i] && cost[choosed][i] < label[i]) {
label[i] = cost[choosed][i];
}
}
}
return rst;
}
void addEdge(int id, int s, int t, int d)
{
edge[id].s = s;
edge[id].t = t;
edge[id].d = d;
}
bool cmp(Edge edge1, Edge edge2)
{
return edge1.d