POJ 1861题

//最小生成树:Kruskal算法
#include <stdio.h>
#include <algorithm>
using namespace std;
#define arraysize 15001
#define nodenum 1001
typedef struct node
{
 int start;    //起点
 int end;    //终点
 int w;     //费用
};
node edges[arraysize];  //存储边
node record[arraysize];  //存储最小生成树中的边
int final[nodenum];   //存储该点的双亲节点
int r[nodenum];    //存储以nodenum为根的树的节点数(包括根)
bool cmp(node a,node b)

 return a.w<b.w;
}
int findroot(int n)   //找到n的根节点
{
 if(final[n] == n)
  return n;
 else
 {
  final[n] = findroot(final[n]);
 }
 return final[n];
}
int main()
{
 //freopen("1.txt","r",stdin);
 int N,M;
 while(scanf("%d%d",&N,&M)!=EOF)
 {
  int start,end,w;
  for(int i=1;i<M+1;++i)
  {
   scanf("%d%d%d",&start,&end,&w);
   edges[i].start = start;
   edges[i].end = end;
   edges[i].w = w;
  }
  //Kruskal算法,初始化,建立n棵树
  for(int i1=1;i1<N+1;i1++)
  {
   final[i1] = i1;
   r[i1] = 1;
  }
  //对边进行排序
  sort(edges+1,edges+M+1,cmp);  //此处第一个参数是edges+1,第二个参数是edges+M+1
  int flag = 0;      //记录最小生成树中的边数
  int maxLength = 0;     //记录最小生成树种的最大边
  //遍历所有的边
  for(int i2=1;i2<M+1;++i2)
  {
   int a = edges[i2].start;
   int b = edges[i2].end;
   int w = edges[i2].w;
   //查找边的源点的根节点
   int roota = findroot(a);
   //查找边的终点的根节点
   int rootb = findroot(b);
   //如果边的源点和边的终点不在同一连通子图中,则将该点加入到最小生成树中
   if(roota != rootb)
   {
    flag++;
    record[flag].start = a;
    record[flag].end = b;
    record[flag].w = w;
    if(record[flag].w>maxLength)
    {
     maxLength = record[flag].w;
    }
    if(r[roota]>=r[rootb])
    {
     final[rootb] = a;
     r[roota] += r[rootb];
    }
    else
    {
     final[roota] = b;
     r[rootb] += r[roota];
    }
   }
   if(flag == N-1)  //找到了最小生成树
   {
    printf("%d\n%d\n",maxLength,flag);
    for(int j=1;j<=flag;++j)
    {
     printf("%d %d\n",record[j].start,record[j].end);
    }
    break;
   }
  }
 }  
 return 0;
}

posted @ 2010-04-30 22:26  北海小龙  阅读(234)  评论(0编辑  收藏  举报