描述
南将军率领着许多部队,它们分别驻扎在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
次小生成树 次小生成树可由最小生成树换一条边得到
算法: 1)先用prim求出最小生成树T,在prim的同时,用一个矩阵max[u][v]记录在树中连接u-v的路径中权值最大的边. 2)枚举所有不在T中的边u-v,加入边u-v,删除权值为max[u][v]的边,不断枚举找到次小生成树.
#include <iostream> #include <algorithm> #include <queue> #include <math.h> #include <deque> #include <stack> #include <set> #include <limits> #include <malloc.h> #include <string.h> #include <stdio.h> #include <stdlib.h>. #define MOD 10000 #define ll long long #define MAX 100005 //#define root 1,m,1 #define lson l,mid,rt << 1 #define rson mid+1,r,rt << 1 | 1 using namespace std; const int INF=0x3f3f3f3f; int g[1100][1100],dist[1100],mmax[1100][1100]; int pre[1100]; bool mark[1100]; bool connect[1100][1100]; int mst,mint; int n,m; void prim() { int res=0,fa,p,min,i,j; memset(mmax,0,sizeof(mmax)); for(i=1;i<=n;i++) { dist[i]=g[1][i]; pre[i]=1;//标记所有节点的依附点皆为默认的1号节点 mark[i]=false; } dist[1]=0; mark[1]=true;//第一个节点是在集合里的 for(i=1;i<n;i++) { p=-1;min=INF; for(j=1;j<=n;j++) { if(!mark[j]&&dist[j]<min)//边权值小且不再生成树中 { p=j; min=dist[j]; } } if(p==-1) return ; mark[p]=true;//把p放入集合中 res+=min; fa=pre[p]; connect[fa][p]=false; connect[p][fa]=false; mmax[fa][p]=min; for(j=1;j<=n;j++)//更新权值和依附点 { if(!mark[j]&&dist[j]>g[p][j]) { dist[j]=g[p][j]; pre[j]=p; } } for(j=1;j<=n;j++) mmax[j][p]=(mmax[fa][p]>mmax[j][fa])?mmax[fa][p]:mmax[j][fa]; } return ; } int main() { int tc; //freopen("1.txt","r",stdin); scanf("%d",&tc); while(tc--) { scanf("%d %d",&n,&m); memset(g,INF,sizeof(g)); memset(connect,false,sizeof(connect)); while(m--) { int u,v,c; scanf("%d %d %d",&u,&v,&c); g[u][v]=c; g[v][u]=c; connect[u][v]=true; connect[v][u]=true; } prim(); int i,j; bool flag=false; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(connect[i][j]==false||g[i][j]==INF) continue; if(g[i][j]==mmax[i][j]) { flag=true; break; } } if(flag) printf("Yes\n"); else printf("No\n"); } return 0; }