HDOJ 1863

来源:互联网 发布:皮鞋和运动鞋尺码 知乎 编辑:程序博客网 时间:2024/05/13 19:27

题目大意:输入N,M表示道路的数目,和村庄的数目,接下来输入N行,每行输入一条道路的起始端点,终止端点,道路权值,输出所有村庄联通的最小代价,若是没有最小代价则输出“?”,测试用例的输入以N=0为结束标志。

算法思想:

  1.定义一个结构体Edge用于存储道路的两个端点及权值。

   2.扫描所有的边,按从递增的顺序进行排序。

   3.采用克鲁斯卡尔算法构造最小生成树。(克鲁斯卡尔算法即选边法详见算法导论p348)

    4.输出结果。

代码如下:

#include <iostream>#include <algorithm>#include <cstring>using namespace std;const int MAXN=105;int node[MAXN];/*存储边结构*/typedef struct edge{    int start;//起始端点    int end;//终止端点    int value;//权值}Edge;Edge Road[5000];//存储道路/*比较函数*/bool cmp(Edge a,Edge b){    if(a.value<b.value) return true;    return false;}/*并查集:寻找根*/int Find_set(int n){   if(node[n]==-1)      return n;   return node[n]=Find_set(node[n]);}/*将一条边的两个端点加入到一个集合中*/bool Merge(int a,int b){    int r1=Find_set(a);    int r2=Find_set(b);    if(r1==r2) return false;    if(r1<r2)    {         node[r2]=r1;    }        if(r2<r1){         node[r1]=r2;    }    return true;}int main(){   int N,M,num,cost;   while(cin>>N>>M&&N!=0){       memset(node,-1,sizeof(node));       cost=0;//记录最小代价       num=0;//记录所选的边数       for(int i=0;i<N;i++){//输入所有的道路          cin>>Road[i].start>>Road[i].end>>Road[i].value;       }       sort(Road,Road+N,cmp);           for(int i=0;i<N;i++){          if(Merge(Road[i].start,Road[i].end))          {            num++;            cost+=Road[i].value;           }          if(num==M-1) break;       }       if(num==M-1) cout<<cost<<endl;       else cout<<"?"<<endl;   }   return 0;}


0 0