hdu1863-----------------联通工程(并查集加mst)
这道题先判断给出的路能否让村庄联通,如果能够联通就输出最少要修多长的路,如果不能联通,就输出“?”。
判联通时,用并查集,判断这些村庄能否在一个集合。 如果在一个集合,接着用prim算法求最小生成树。哈哈哈,幸亏我先前研究过并查集。很简单,简直是两个模板的综合。 0ms ,AC!好爽
AC:
#include<stdio.h>
#include<string.h>
int map[101][101];
int low[101];
int visit[101];
int set[101];
int n,m; //n条路, m个村儿
int find(int x)
{
int r;
r=x;
while(set[r]!=r)
r=set[r];
return r;
}
void merge(int x,int y)
{
int fx,fy;
fx=find(x);
fy=find(y);
if(fx!=fy)
set[fx]=fy;
}
int prim()
{
int result=0;
int i,j,k,pos,min;
memset(visit,0,sizeof(visit));
pos=1;
visit[pos]=1;
for(i=1;i<=m;i++)
{
if(i!=pos)
low[i]=map[pos][i];
}
for(i=1;i<m;i++)
{
min=100000000;
for(j=1;j<=m;j++)
{
if(!visit[j]&&min>low[j])
{
min=low[j];
pos=j;
}
}
result+=min;
visit[pos]=1;
for(j=1;j<=m;j++)
{
if(!visit[j]&&map[pos][j]<low[j])
low[j]=map[pos][j];
}
}
printf("%d\n",result);
return 0;
}
int main()
{
int i,j,k;
int s,e,w;
int count; //记录村庄能够组成几个集合
while(scanf("%d%d",&n,&m)!=EOF&&n!=0)
{
for(i=1;i<=m;i++)
set[i]=i;
for(i=1;i<=m;i++)
for(j=1;j<=m;j++)
map[i][j]=100000000;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&s,&e,&w);
merge(s,e);
map[s][e]=map[e][s]=w;
}
count=0;
for(i=1;i<=m;i++) //如果村庄全部连通的话,只能有一个集合, 即 count=1
{
if(set[i]==i)
count++;
}
if(count>1)
printf("?\n");
else
prim();
}
return 0;
}