修路方案
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
5
-
描述
-
南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路。
现在已经知道哪些城市之间可以修路,如果修路,花费是多少。
现在,军师小工已经找到了一种修路的方案,能够使各个城市都联通起来,而且花费最少。
但是,南将军说,这个修路方案所拼成的图案很不吉利,想让小工计算一下是否存在另外一种方案花费和刚才的方案一样,现在你来帮小工写一个程序算一下吧。
-
输入
-
第一行输入一个整数T(1<T<20),表示测试数据的组数
每组测试数据的第一行是两个整数V,E,(3<V<500,10<E<200000)分别表示城市的个数和城市之间路的条数。数据保证所有的城市都有路相连。
随后的E行,每行有三个数字A B L,表示A号城市与B号城市之间修路花费为L。
输出
- 对于每组测试数据输出Yes或No(如果存在两种以上的最小花费方案则输出Yes,如果最小花费的方案只有一种,则输出No) 样例输入
-
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
样例输出
-
No Yes
来源
- POJ题目改编 上传者
-
张云聪
没看懂次小生成树,仿照别人的代码自己写了一个,以后就仿照这个模板写,直到自
己领悟为止!
#include<cstdio> #include<iostream> #include<cstring> const int infinity=0x3f3f3f3f; const int maxnum=505; using namespace std; int nodenum; int map1[maxnum][maxnum],visited[maxnum],low[maxnum];//最小生成树基本变量 int mmax[maxnum][maxnum],pre[maxnum],connect[maxnum][maxnum];//次小生成树必须变量 void prim() { int result=0,i,j,Min,pos=1,fa; memset(visited,0,sizeof(visited));//初始化都未标记 memset(mmax,0,sizeof(mmax));//*****mmax初始化为0***** for(i=1;i<=nodenum;i++) { low[i]=map1[pos][i]; pre[i]=pos;//*****把所有的点的前节点记录为1***** } low[pos]=0; visited[pos]=1;//把1号作为起点 for(i=2;i<=nodenum;i++)//这个i没有其他的意思就是一个循环次数 { Min=infinity;pos=-1;//从1号开始找最小的边 for(j=1;j<=nodenum;j++) { if(!visited[j]&&Min>low[j]) { Min=low[j]; pos=j; } } if(pos==-1) { return ; } visited[pos]=1;//做到与1os号最近的边 result+=Min;//加权值 fa=pre[pos];//*****取得这个点的前节点***** connect[fa][pos]=connect[pos][fa]=0;//*****让前节点与当前点不是联通的! mmax[fa][pos]=Min;//*****设置前点与当前点的距离为Min***** for(j=1;j<=nodenum;j++) { if(!visited[j]&&low[j]>map1[pos][j]) { low[j]=map1[pos][j];//这个就是替换未被标记的最小权值! pre[j]=pos;//*****更新此时所有被更换权值节点的前节点为pos***** } } //*****以下为次小生成树新增***** for(j=1;j<=nodenum;j++) { mmax[j][pos]=mmax[fa][pos]>mmax[j][fa]?mmax[fa][pos]:mmax[j][fa];//更新次小权值 } //*****以上为次小生成树新增***** } return ; } int main() { int t,m,i,j,a,b,c,flag; cin>>t; while(t--) { memset(map1,infinity,sizeof(map1)); /* for(i=1;i<=nodenum;i++) { for(j=1;j<=nodenum;j++) { map1[i][j]=infinity; } }把这个替换成上面那个就WA了不知道为什么,以后注意一点! */ memset(connect,0,sizeof(connect));//***** cin>>nodenum>>m; while(m--) { cin>>a>>b>>c; if(c<map1[a][b]) { map1[a][b]=map1[b][a]=c; connect[a][b]=connect[b][a]=1;//***** } } prim(); flag=0; for(i=1;i<=nodenum;i++) { for(j=1;j<=nodenum;j++) { if(connect[i][j]==0||map1[i][j]==infinity) { continue; } if(map1[i][j]==mmax[i][j]) { flag=1; break; } } } if(flag) { cout<<"Yes"<<endl; } else { cout<<"No"<<endl; } } }
-
第一行输入一个整数T(1<T<20),表示测试数据的组数
747

被折叠的 条评论
为什么被折叠?



