hdu 1233 还是畅通工程
http://acm.hdu.edu.cn/showproblem.php?pid=1233
这个题我用的贪心和并查集来解决的。
(kruskal算法)
首先用贪心对长度排序,然后按照长度从小到大选择连接,没有被联通的则直接连,要注意一个问题就是如果4个村庄是1 4联通了, 2 3联通了,那么肯定还要让这两个集合联通(用并查集)。
因此我用了一个p来表示不同的集合。
AC代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; struct Node { int a,b; int l; }a[5010]; bool cmp(Node a, Node b) { return a.l < b.l; } int main() { int n,i,j,sum,p,t; int b[110]; //记录这个村庄是否已经联通 while(scanf("%d",&n)&&n) { sum = 0; //初始化总费用 memset(b,0,sizeof(b)); //初始化所有村庄不连通 for(i = 0; i < n*(n-1)/2; i++) { scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].l); } sort(a,a+n*(n-1)/2,cmp); //权值从小到大排序 p = 1; for(i = 0; i < n*(n-1)/2; i++) { if(b[a[i].a] == 0 || b[a[i].b] == 0) { sum += a[i].l; if(b[a[i].a] == 0 && b[a[i].b] == 0) //如果两个都没有被联通过,则为新联通图集合 { b[a[i].a] = b[a[i].b] = p; p++; } else { if(b[a[i].a] != 0) { b[a[i].b] = b[a[i].a]; } else { b[a[i].a] = b[a[i].b]; } } if(b[a[i].a] != b[a[i].b]) //连个村庄在两个图的时候 { t = b[a[i].b]; sum += a[i].l; for(j = 1; j <= n; j++) //两集合合并 { if(b[j] == t) { b[j] = b[a[i].a]; } } } } printf("%d\n",sum); } return 0; }