*/
3 1 2 1 0 1 3 2 0 2 3 4 0 3 1 2 1 0 1 3 2 0 2 3 4 1 3 1 2 1 0 1 3 2 1 2 3 4 1 0
3 1 0
#include <iostream> #include <cstring> #include <cstdio> #define MAXN 103 #define INF 999999999 using namespace std; int map[MAXN][MAXN],visit[MAXN],dis[MAXN],N; int prim() { for(int i = 1;i <= N; i++) { dis[i] = map[i][1]; } dis[1] = 0; visit[1] = 1; int sum = 0; for(int i = 1; i <= N-1; i++) { int temp = INF,pos; //for(int j = 1; j <= N; j++) for(int j = 1; j <= N; j++) { if(!visit[j] && temp > dis[j]) { temp = dis[j]; pos = j; } } if(temp == INF)break; visit[pos] = 1; sum += dis[pos]; for(int j = 1; j <= N; j++) { if(!visit[j] && map[pos][j] < dis[j] && map[pos][j]!=INF) { dis[j] = map[pos][j]; } } } return sum; } int main() { while(scanf("%d",&N),N) { memset(map,0x3f,sizeof(map)); memset(visit,0,sizeof(visit)); for(int i = 1; i <= (N*(N-1))/2; i++) { int u,v,w,x; scanf("%d%d%d%d",&u,&v,&w,&x); if(x == 1)w = 0; // 如果x为1,即已经建成,则两条路长度为0 map[u][v] = map[v][u] = w; } printf("%d\n",prim()); } }
#include <cstdio> #include <cstdlib> #include <algorithm> #include <iostream> using namespace std; const int M = 5050; int p[M]; struct edge {//边节点 int a; int b; int w; }e[M]; int cmp(edge a, edge b) {//按权值从小到大排序 return a.w < b.w; } int find(int v) {//并查集路径压缩 if (p[v] != v) p[v] = find(p[v]); return p[v]; } int join(edge e) { //加入生成树,如果已经在同一棵树种,则不加入,即贡献长度为0 int x, y; x = find(e.a); y = find(e.b); if (x != y) { p[x] = y; return e.w; } return 0; } int kruskal(int es, int vs) { int ans = 0; for (int i=1; i<=vs; ++i)//初始化集合 p[i] = i; sort(e,e+es, cmp); for (int i=0; i<es; ++i) ans += join(e[i]); return ans; } int main() { int vs, f; //vs点 ,f表示状态(是否已经修建) while (scanf("%d", &vs), vs) { int es = vs * (vs - 1) / 2; //es表示边数量 for (int i=0; i<es; ++i) { scanf("%d%d%d%d", &e[i].a, &e[i].b, &e[i].w, &f); if (f) e[i].w = 0; } int ans = kruskal(es, vs); printf ("%d\n", ans); } return 0; }
kruskal适合边稀疏图;