最小生成树模板(嗯……在kuangbin模板里面抄的……)
最小生成树(prim) /** Prim求MST * 耗费矩阵cost[][],标号从0开始,0~n-1 * 返回最小生成树的权值,返回-1表示原图不连通 */ const int INF = 0x3f3f3f3f; const int MAXN = 110; bool vis[MAXN]; int lowc[MAXN]; int map[MAXN][MAXN]; int Prim(int cost[][MAXN], int n) { int ans = 0; memset(vis, false, sizeof(vis)); vis[0] = true; for (int i = 1; i < n; ++i) lowc[i] = cost[0][i]; for (int i = 1; i < n; ++i) { int minc = INF; int p = 1; for (int j = 0; j < n; ++j) if (!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } if (minc == INF) return -1; ans += minc; vis[p] = true; for (int j = 0; j < n; ++j) if (!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; }
感觉Prim和Dijkstra有点像。写起来挺简单的。
我一开始的想法是把每个q中的a,b设为已访问节点,后来发现不对,例如ab连,dc连,但它们并不是全部相连的。
好吧其实此题就是把已建好两点之间距离设为0.
//Problem : 1102 ( Constructing Roads ) Judge Status : Accepted #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N = 105; const int INF = 3000; int map[N][N]; int vis[N]; int dis[N]; int Prim(int n) { int ans = 0; memset(vis, 0, sizeof(vis)); for (int j = 1; j <= n; ++j) { dis[j] = map[1][j]; } for (int k = 1; k <= n; ++k) { int minc = INF; int p = 1; for (int i = 1; i <= n; ++i) { if (!vis[i] && dis[i] < minc) { minc = dis[i]; p = i; } } if (minc == INF) return -1; ans += minc; vis[p] = 1; for (int j = 1; j <= n; ++j) { if (map[p][j] < dis[j] && !vis[j]) dis[j] = map[p][j]; } } return ans; } int main() { int n, q; while (cin >> n) { for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) cin >> map[i][j]; cin >> q; int a, b; for (int i = 0; i < q; ++i) { cin >> a >> b; map[a][b] = map[b][a] = 0; } cout << Prim(n) << endl; } return 0; }