修路方案
时间限制:
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
-
次小生成树讲解
-
#include<cstdio> #include<cstdlib> #include<cstring> #define inf 0x3f3f3f3f using namespace std; const int max=505; int map[max][max],use[max][max],f[max][max]; int low[max],vis[max],pre[max],n,sum1,sum2; void prime(){ int pos,i,j,result=0,min;sum1=0; memset(vis,0,sizeof(vis)); memset(f,0,sizeof(f)); pos=1;vis[pos]=1; for(i=1;i<=n;++i){ low[i]=map[pos][i]; pre[i]=1; }low[1]=0; for(j=1;j<=n;++j){ min=inf; for(i=1;i<=n;++i){ if(!vis[i]&&min>low[i]){ min=low[i];pos=i; } } if(min==inf)break; use[pre[pos]][pos]=use[pos][pre[pos]]=0; sum1+=min;vis[pos]=1; for(i=1;i<=n;++i){ if(vis[i]){ f[i][pos]=f[pos][i]=f[i][pre[pos]]>map[pre[pos]][pos]?f[i][pre[pos]]:map[pre[pos]][pos]; } if(!vis[i]&&low[i]>map[pos][i]){ low[i]=map[pos][i]; pre[i]=pos; } } } } void second_prime(){ int i,j,result;sum2=inf; for(i=1;i<=n;++i){ for(j=1;j<=n;++j){ if(use[i][j]){ sum2=sum2<sum1-f[i][j]+map[i][j]?sum2:sum1-f[i][j]+map[i][j]; } } } } int main() { int k,m,i,j,l,a,b; scanf("%d",&k); while(k--){ memset(map,0x3f,sizeof(map)); memset(use,0,sizeof(use)); scanf("%d%d",&n,&m); for(i=1;i<=m;++i){ scanf("%d%d%d",&a,&b,&l); map[a][b]=map[b][a]=l; use[a][b]=use[b][a]=1; } prime(); second_prime(); sum1==sum2?printf("Yes\n"):printf("No\n"); } return 0; }