51nod_1212_无向图最小生成树(模板题)
基准时间限制: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
prim 每次向树中加一个点
// prim #include <iostream> #include <algorithm> using namespace std; #define maxn 1005 #define INF 99999999 bool visit[maxn]; int min_dis[maxn]; int map_dis[maxn][maxn]; int n, m; int s, e, w; int prim() { for (int i = 0; i < n; i++) { visit[i] = false; min_dis[i] = INF; } min_dis[0] = 0; // visit[0] = true; int sum = 0; while (true) { int pos = -1; for (int i = 0; i < n; i++) { if (!visit[i] && (pos == -1 || min_dis[i] < min_dis[pos])) { pos = i; } } // cout << 1 << endl; if (pos == -1) { break; } else { sum += min_dis[pos]; //cout << "sum = " << sum << endl; //cout << "pos = " << pos << endl; } visit[pos] = true; for (int i = 0; i < n; i++) { if (!visit[i] && map_dis[pos][i] < min_dis[i]) { min_dis[i] = map_dis[pos][i]; } } } return sum; } int main() { while (cin >> n >> m) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { map_dis[i][j] = INF; } } for (int i = 0; i < m; i++) { cin >> s >> e >> w; s -= 1; e -= 1; map_dis[s][e] = w; map_dis[e][s] = w; } int result = prim(); cout << result << endl; } return 0; }
Kruskal 每次向树中加一条边
// Kruskal #include <iostream> #include <algorithm> using namespace std; #define maxn 60000 int father[maxn]; int son[maxn]; struct line { int a, b, value; }; // 边按权值大小排序 bool cmp(line & a, line & b) { return a.value < b.value; } int check_tree_root(int x) { // 递归找到 树根 并返回 return x == father[x] ? x : check_tree_root(father[x]); } // 检查 x 和 y 所在的两个树是否可以合并 bool join(int x, int y) { int root1 = check_tree_root(x); int root2 = check_tree_root(y); // x 和 y 属于同一棵树 if (root1 == root2) { return false; } else { // 树根为 root1 的树规模较大 if (son[root1] >= son[root2]) { father[root2] = root1; son[root1] += son[root2]; } else { father[root1] = root2; son[root2] += son[root1]; } } return true; } int main() { int v, e; line node[maxn]; cin >> v >> e; for (int i = 0; i < e; i++) { cin >> node[i].a >> node[i].b >> node[i].value; } for (int i = 0; i <= v; i++) { // 初始情况 每个单独的节点都是一颗树 // 树根是自己本身 , 树的节点数 为 1 father[i] = i; son[i] = 1; } sort(node, node + e, cmp); int sum_e = 0; int sum = 0; bool flag = false; for (int i = 0; i < e; i++) { // 如果可以加边 if (join(node[i].a, node[i].b)) { sum_e++; sum += node[i].value; } if (sum_e == v - 1) { flag = true; break; } } if (flag == true) { cout << sum << endl; } return 0; }