hdu 1233 还是畅通工程
/*
只与边的个数有关
算法:
1:将个边按权值大小进行排序
2: 遍历一次,找出最小权值的边,(条件:此次找出的边不能和已加入最小生成树集合的边构成环)
若符合条件,则加入最小生成树的集合中。不符合则继续找。
3:重复上述步骤,直到找到n-1条边(假设有n个节点)
*/
#include"stdio.h" #include"stdlib.h" int set[5000]; struct node { int a,b,dis; }aa[5002]; int find(int x) { int r,i; r=x; while(r!=set[r]) r=set[r]; while(set[x]!=r) { i=set[x]; set[x]=r; x=i; } return r; } int cmp(const void*a,const void*b) { struct node *c,*d; c=(struct node*)a; d=(struct node*)b; return c->dis-d->dis; } int main() { int n,m,i,j,ans; int x,y; while(scanf("%d",&n)!=EOF&&n) { m=n*(n-1)/2; for(i=0;i<=5000;i++) set[i]=i; for(i=0;i<m;i++) scanf("%d%d%d",&aa[i].a,&aa[i].b,&aa[i].dis); qsort(aa,m,sizeof(aa[0]),cmp); ans=0; for(i=0;i<m;i++) { x=find(aa[i].a); y=find(aa[i].b); if(x!=y) { ans+=aa[i].dis; if(x<y) set[y]=x; else set[x]=y; } } printf("%d\n",ans); } return 0; }
普利姆(Prime)算法(只与顶点相关)
算法描述:
普利姆算法求最小生成树时候,和边数无关,只和定点的数量相关,所以适合求稠
密网的最小生成树,时间复杂度为O(n*n)。
算法过程:
1.将一个图的顶点分为两部分,一部分是最小生成树中的结点(A集合),另一部分
是未处理的结点(B集合)。
2.首先选择一个结点,将这个结点加入A中,然后,对集合A中的顶点遍历,找出A中
顶点关联的边权值最小的那个(设为v),将此顶点从B中删除,加入集合A中。
3.递归重复步骤2,直到B集合中的结点为空,结束此过程。
4.A集合中的结点就是由Prime算法得到的最小生成树的结点,依照步骤2的结点连接
这些顶点,得到的就是这个图的最小生成树。
#include"stdio.h" #include"string.h" #define INF 99999999 int map[100][100],dis[100]; int mark[100]; int n; void prime() { int i,j,k,min,sum; for(i=1;i<=n;i++) dis[i]=map[1][i]; memset(mark,0,sizeof(mark)); mark[1]=1; sum=0; for(i=2;i<=n;i++) { min=INF; for(j=2;j<=n;j++) { if(!mark[j]&&dis[j]<min) { min=dis[j];k=j; } } sum+=min; mark[k]=1; for(j=2;j<=n;j++) { if(!mark[j]&&map[j][k]<dis[j]) dis[j]=map[j][k]; } } printf("%d\n",sum); } int main() { int i,j,x,y,d; while(scanf("%d",&n)!=EOF&&n) { memset(map,0,sizeof(map)); for(i=1;i<=n;i++) map[i][i]=INF; j=n*(n-1)/2; for(i=0;i<j;i++) { scanf("%d%d%d",&x,&y,&d); map[x][y]=map[y][x]=d; } prime(); } return 0; }