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;
}

posted on 2012-03-17 17:45  hrbust_09zhangyabin  阅读(248)  评论(0编辑  收藏  举报