现在的位置: 首页 > 综合 > 正文

pku1861Network

2013年10月06日 ⁄ 综合 ⁄ 共 1390字 ⁄ 字号 评论关闭

最小生成树的题目,并查集应用最完美的地方:最小生成树的 kruskal 算法

呵呵,第一次用并查集,具有纪念价值,所以附上代码,并有详细的注释。最短时间把它给攻下!!!

#include<iostream>
#include<algorithm>
using namespace std;
struct node  //存储边信息的结点
{
   int a,b;  //一条边的两个点
   int value;//边权值
}edge[15005];
node record[15005];//用来记录
int father[1005];//父结点
int rank[1005]; //秩
bool cmp(node a,node b)
{
     return a.value<b.value;
}
void Make_Set(int n)//初始化一个集合
{
   for(int i=0;i<=n;i++)
   {
      father[i]=i;
      rank[i]=1;
   }
}
int Find_Set(int x)//查找一个元素所在集合
{
    if(x!=father[x])
    {
       father[x]=Find_Set(father[x]);//递归查找
    }
    return father[x];
}
bool Union(int a,int b)
{
    int x=Find_Set(a);
    int y=Find_Set(b);
    if(x==y)return false;
    // 合并将元素少的合并到元素多的集合中,使的树的高度相对较小
    if(rank[x]>=rank[y])
    {
       father[y]=x;
       rank[x]+=rank[y];
    }
    else
    {
        father[x]=y;
        rank[y]+=rank[x];
    }
    return true;
}
int main()
{
    int i,j=1,n,m,max=0,num=0;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
      scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].value);
    Make_Set(n);
    sort(edge+1,edge+m+1,cmp);
    for(i=1;i<=m;i++)
    {
       if(Union(edge[i].a,edge[i].b))
       {
          num++;
          if(edge[i].value>max)
            max=edge[i].value;
          record[j].a=edge[i].a;
          record[j].b=edge[i].b;
          j++;
       }
       if(num==n-1)break;
    }
    printf("%d/n%d/n",max,n-1);
    for(i=1;i<n;i++)
      printf("%d %d/n",record[i].a,record[i].b);
    system("pause");
    return 0;
}
   
      
        
        
      
   
     
   

抱歉!评论已关闭.