赞
踩
因为我们要学习算法的多样性,所以我们这道题采取更为简单的算法Kruskal具体代码讲解如下
- #include<bits/stdc++.h>
- using namespace std;
- typedef struct Edge
- {
- int x,y,z;
- }op;//定义输入方便的结构体x为起点,y为终点,z为权值
- bool cmp(op a,op b)
- {
- return a.z<b.z;//以小为排序规则
- }
- int p[1000]; //并查集数组
- int find(int x)//并查集
- {
- if(p[x]!=x)p[x]=find(p[x]);
- return p[x];
- }
- set<int>hi;//为的是找出对应集合
- int main()
- {
- int a,b;cin>>a>>b;
- for(int i=1;i<=a;i++)p[i]=i;//并查集始初化
- op mp[250000];//定义的大一点容易溢出
- int gp[1000];//这个是为了储存结点的距离方便之后减去操作
- int vist[1000];//是否用过该边的一个判断数组
- for(int i=0;i<b;i++)vist[i]=0;//始初化
- int sum=0;
- int cot=0;
- for(int i=0;i<b;i++)
- {
- cin>>mp[i].x>>mp[i].y>>mp[i].z;//输入对应权值和出发起始点
- }
- sort(mp,mp+b,cmp);//排序
- for(int i=0;i<b;i++)//开始算法
- {
- int as=find(mp[i].x);//找到祖宗
- int ad=find(mp[i].y);//找到祖宗
- if(as!=ad)//不是一个祖宗构不成环
- {
- p[as]=ad;//组成一个环
- cot++;//边数加1
- sum+=mp[i].z;//总距离加起来
- vist[i]=1;//该边使用过
- gp[mp[i].x]=gp[mp[i].y]=mp[i].z;//保存对应边值
- }
- }
- if(cot<a-1)//如果边数使用太少则不能全部相连
- {
- for(int i=1;i<=a;i++)
- {
- hi.insert(find(i));//插入每一个的祖宗
- }
- cout<<"No MST"<<endl;
- cout<<hi.size();//输出祖宗数量,即集合树数
- return 0;
- }
- cout<<sum<<endl;//反之则可以构成最小树
- for(int i=0;i<b;i++)
- {
- if(!vist[i])//如果该边没用过则交换去除一个边加上可以替代的另一个边
- {
- int as=mp[i].x;
- int ad=mp[i].y;
- int res=mp[i].z;
- if(sum-gp[as]+res==sum)//如果成功被替代则不是唯一
- {
- cout<<"No";
- return 0;
- }
- }
- }
- cout<<"Yes";//反之则是唯一
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。