poj1861 并查集

来源:互联网 发布:post请求发送json数据 编辑:程序博客网 时间:2024/06/10 23:16

 

 

   如题:http://poj.org/problem?id=1861

 

   题目要求给出边和权 求最大的那条边最小的最小生成树。

   最大边最小,可以用克鲁斯卡尔算法。

  将权排序后,一个个并入集合,期间记录最大值。直到仅剩一个集合。

 

 

 

#include<iostream>
using namespace std;

#define MAX 15001
typedef struct
{
 int x,y;
 int w;
}edge;

edge e[MAX];
edge v[MAX];
int rank[MAX];
int father[MAX];
int cmp(const void * a,const void * b)
{
 return ((edge *)a)->w-((edge *)b)->w;
}

void Make_Set(int x)
{
 father[x]=x;
 rank[x]=0;
}

int Find_Set(int x)
{
 if(x!=father[x])
  father[x]=Find_Set(father[x]);
 return father[x];
}

void Union(int x,int y)
{
 if(x==y) return;
 if(rank[x]>rank[y])
  father[y]=x; // 并入较深的集合
 else
 {
  if(rank[x]==rank[y])
   rank[y]++;
  father[x]=y;
 }
}

int main()
{
 int i,m,n,k,max;
 int x,y;
 scanf("%d%d",&m,&n);
 for(i=0;i<n;i++)
  scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].w);

 for(i=0;i<m;i++)
  Make_Set(i);

 qsort(e,n,sizeof(edge),cmp); //从小到大队权排序

 k=0;
 max=0;

 for(i=0;i<n;i++)
 {
  x=Find_Set(e[i].x);
  y=Find_Set(e[i].y);
  if(x!=y)
  {
   k++;
   Union(x,y);
   v[k]=e[i];
   if(max<e[i].w)
    max=e[i].w;
  }
 }
 printf("%d\n",max);
 printf("%d\n",k);
 for(i=1;i<=k;i++)
  printf("%d %d\n",v[i].x,v[i].y);
 return 0;
}

 

0 0
原创粉丝点击