终于把杭电的畅通系列做光了,图论的算法总算是初步有点入门了
这道题也不难,但是主要数组要开大点就可以。先用并查判断连通性,然后用prim就可以搞定了
#include <iostream> using namespace std; #define inf 1000000 int set[1001],Dis[1001][1001],sum; struct Edge { int point; int lowcost; }edge[1001]; int find(int x) { int i,j,r = x; while (set[r] != r) { r = set[r]; } i = x; while (i != r) { j = set[i]; set[i] = r; i = j; } return r; } void merge(int a,int b) { int x = find(a); int y = find(b); if (x != y) set[x] = y; }
int main() { int n,m,i,j,k,a,b,x,r; while (scanf("%d %d",&n,&m) == 2 && n != 0) { for (i = 0;i <= m;i++) { set[i] = i; for (j = 0;j <= m;j++) Dis[i][j] = inf; } for (i = 1;i <= n;i++) { scanf("%d %d %d",&a,&b,&x); merge(a,b); if (x < Dis[a][b]) Dis[a][b] = Dis[b][a] = x; } r = 0; for (i = 1;i <= m;i++) if (set[i] == i) r++; sum = 0; if (r == 1) { k = 0; int min; j = 1; for (i = 1;i <= m;i++) { edge[i].point = i; edge[i].lowcost = Dis[j][i]; } edge[j].lowcost = 0; for (i = 1;i <= m;i++) { min = inf; for (j = 1;j <= m;j++) { if (edge[j].lowcost != 0 && edge[j].lowcost < min) { k = j; min = edge[j].lowcost; } } sum += edge[k].lowcost; edge[k].lowcost = 0; for (j = 1;j <= m;j++) { if (Dis[k][j] < edge[j].lowcost) { edge[j].point = k; edge[j].lowcost = Dis[k][j]; } } } printf("%d\n",sum); } else printf("?\n"); } return 0; }