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;
}
浙公网安备 33010602011771号