最小生成树专题
Prim算法。
View Code
#include <cstdio> #include <cstring> #define MAXN 110 int d[MAXN][MAXN]; int edge[MAXN]; bool visit[MAXN]; int n; int Prim() { int i, j, k, mst = 0; memset(visit, false, sizeof(visit)); memset(edge, 0x3f, sizeof(edge)); edge[0] = 0; for(i = 0; i < n; i ++) { k = -1; for(j = 0; j < n; j ++) if(!visit[j] && (k == -1 || edge[j] < edge[k])) k = j; visit[k] = true; mst += edge[k]; for(j = 0; j < n; j ++) { if(!visit[j] && d[k][j] && d[k][j] < edge[j]) edge[j] = d[k][j]; } } return mst; } int main() { while(~scanf("%d", &n)) { for(int i = 0; i < n; i ++) { for(int j = 0; j < n; j ++) { scanf("%d", &d[i][j]); } } printf("%d\n", Prim());; } return 0; }
Kruskal算法。
View Code
#include <cstdio> #include <algorithm> #define MAXN 100100 using namespace std; int u[MAXN], v[MAXN], w[MAXN], p[MAXN], r[MAXN]; int n, m, id; int cmp(const int i, const int j) { return w[i] < w[j]; } int find(int x) //并查集,保证放入的边不构成环 { return p[x] == x ? x : p[x] = find(p[x]); } int Kruskal() { int mst = 0; for(int i = 0; i < n; i ++) //初始化并查集的根节点为自己 p[i] = i; for(int i = 0; i < m; i ++) // 边编号 r[i] = i; sort(r, r + m, cmp); for(int i = 0; i < m; i ++) { int e = r[i]; int x = find(u[e]); int y = find(v[e]); if(x != y) // x == y表示新加入的边会构成环,所以即使当前的边是最小权值,也不能要 { mst += w[e]; p[x] = y; // 将新加入的安全边的两个端点加入并查集,可以以任意一个点为根,所以写成p[y] = x也是可以的 } } return mst; } int main() { //freopen("in.txt", "r", stdin); while(~scanf("%d", &n)) { id = 0; m = n * n; for(int i = 0; i < n; i ++) { for(int j = 0; j < n; j ++) { u[id] = i, v[id] = j; scanf("%d", &w[id ++]); } } printf("%d\n", Kruskal()); } return 0; }
View Code
/* Memory: 568K Time: 172MS Language: C++ Result: Accepted */ #include <cstdio> #include <cstring> #define MAXN 510 int d[MAXN][MAXN]; int min[MAXN]; bool flag[MAXN]; int n, m; int Prim() { int max = 0; int i, j, k; memset(min, 0x3f, sizeof(min)); memset(flag, false, sizeof(flag)); min[0] = 0; for(i = 0; i < n; i ++) { k = -1; for(j = 0; j < n; j ++) { if(!flag[j] && (k == -1 || min[j] < min[k])) k = j; } flag[k] = true; if(min[k] > max) { max = min[k]; } for(j = 0; j < n; j ++) { if(!flag[j] && d[k][j] && d[k][j] < min[j]) min[j] = d[k][j]; } } return max; } int main() { int t; scanf("%d", &t); while(t --) { scanf("%d", &n); for(int i = 0; i < n; i ++) { for(int j = 0; j < n; j ++) { scanf("%d", &d[i][j]); } } printf("%d\n", Prim()); } return 0; }
View Code
/* Memory: 820K Time: 297MS Language: C++ Result: Accepted */ #include <cstdio> #include <algorithm> #define MAXN 250010 using namespace std; int w[MAXN], r[MAXN], p[MAXN], u[MAXN], v[MAXN]; int n, m; int find(int x) { return p[x] == x ? p[x] : p[x] = find(p[x]); } bool cmp(int i, int j) { return w[i] < w[j]; } int Kruskal() { int i, max = 0; m = n * n; for(i = 0; i < n; i ++) p[i] = i; for(i = 0; i < m; i ++) r[i] = i; sort(r, r + m, cmp); for(i = 0; i < m; i ++) { int e = r[i]; int x = find(u[e]); int y = find(v[e]); if(x != y) { if(w[e] > max) max = w[e]; p[x] = y; } } return max; } int main() { int t; scanf("%d", &t); while(t --) { int id = 0; scanf("%d", &n); for(int i = 0; i < n; i ++) { for(int j = 0; j < n; j ++) { u[id] = i, v[id] = j; scanf("%d", &w[id ++]); } } printf("%d\n", Kruskal()); } return 0; }
努力更新中……