Kruskal+并查集

杭电题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1233

Statistics

 

还是畅通工程

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 26   Accepted Submission(s) : 18

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

Problem Description

某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。

Input

测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。 当N为0时,输入结束,该用例不被处理。

Output

对每个测试用例,在1行里输出最小的公路总长度。

Sample Input

3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0

Sample Output

3
5

Hint

Hint Huge input, scanf is recommended.

Source

浙大计算机研究生复试上机考试-2006年

// 最小生成树(kruskal算法)+并查集
#include <stdio.h>
#define Max  9999999 
int f[101];
int n;

struct Node
{
  int x,y;
  int cost;
}node[10001];

int Find(int x)           //查找函数,若是都在集合中,最终得到的都是集合中最后一个元素
{
    if(f[x]!=x)
        f[x]=Find(f[x]);

    return  f[x];
}

int main()
{
  int i,j,min,x,y,sum;
  while(scanf("%d",&n)==1&&n)
  {
      min=sum=0;
     for(i=1;i<=n;i++)
         f[i]=i;
      for(i=1;i<=n*(n-1)/2;i++)
      {    
          scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].cost);
          j=i;
          while(j>0&&node[j].cost<node[j-1].cost)               //插入排序
          {
              struct Node tmp=node[j];
                node[j]=node[j-1];
                node[j-1]=tmp;
                j--;
          }
      }
   for(i=1;i<=n*(n-1)/2;i++)
   {
       x=Find(node[i].x);
      y=Find(node[i].y);
      if(x!=y)                       //判断元素是否在一个集合内,若不在则插入元素到末尾
      {
         f[x]=node[i].y;
          min+=node[i].cost;
          sum++;
      }
      if(sum==n) break;
   }
   printf("%d\n",min);

/*     for(i=1;i<=n*(n-1)/2;i++)
       printf("%d%d%d\n",node[i].x,node[i].y,node[i].cost);*/
  }
  return 0;
}


你可能感兴趣的:(Kruskal+并查集)