标签:
南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路。
现在已经知道哪些城市之间可以修路,如果修路,花费是多少。
现在,军师小工已经找到了一种修路的方案,能够使各个城市都联通起来,而且花费最少。
但是,南将军说,这个修路方案所拼成的图案很不吉利,想让小工计算一下是否存在另外一种方案花费和刚才的方案一样,现在你来帮小工写一个程序算一下吧。
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
题解:让找是否存在多个最小生成树;枚举每条不在最小生成树中的边,添加这条边到树中,形成一个环,再删除环中不是这条边的最大边;看是否与最小生成树的权值和相等;存在就是yes
大神的解释:
解题思路:花费最少且任意两个城市能够相同,则说明要求最小生成树。而题目中问是否存在另外一种方案,达到
最小生成树的效果,所以可以采用次小生成树
常用的一种方法就是在求出最小生成树的基础上进行添加边
具体实现:先用prim算法求出最小生成树,并且统计任意一点到其他各点的路径上的最大边权。然后添加改生成树上没有的边(u,v),添加一条边后就会形成环,
然后删除该环中权值大二大的边(即除(u,v)之外的最大权值的边),然后再次统计此时的的费用,如果和最小生生成树的费用相同,则说明存在另外一种方案。
其中:
mp!=-1代表不在最小生成树中的边,mx[i][j]代表i到j的最大边,主判断sum-mx[i][j]+mp[i][j]==sum
代码:
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<queue> #include<vector> using namespace std; const int INF=0x3f3f3f3f; #define mem(x,y) memset(x,y,sizeof(x)) #define SI(x) scanf("%d",&x) #define PI(x) printf("%d",x) typedef long long LL; const int MAXN=520; int mp[MAXN][MAXN]; int mx[MAXN][MAXN]; int vis[MAXN]; int N,sum; vector<int>vec; void prim(int sx){ mem(vis,0); vis[sx]=1; vec.push_back(sx); int u,v; while(vec.size()<N){ int temp=INF; for(int i=0;i<vec.size();i++){ int x=vec[i]; // printf("%d\n",x); for(int j=1;j<=N;j++){ if(!vis[j]&&mp[x][j]!=-1){ if(temp>mp[x][j]){ temp=mp[x][j]; u=x; v=j; // printf("u=%d v=%d\n",u,v); } } } } for(int i=0;i<vec.size();i++){ int x=vec[i]; // printf("u=%d v=%d\n",u,v); if(mx[x][u]<mp[u][v])mx[x][v]=mx[v][x]=mp[u][v]; else mx[x][v]=mx[v][x]=mx[x][u]; } vec.push_back(v); vis[v]=1; sum+=mp[u][v]; mp[u][v]=mp[v][u]=-1; //printf("%d %d %d\n",u,v,vec.size()); } } int main(){ int E,T; SI(T); int a,b,c; while(T--){ mem(mp,-1);mem(mx,-1); SI(N);SI(E); while(E--){ scanf("%d%d%d",&a,&b,&c); mp[a][b]=mp[b][a]=c; mx[a][b]=mx[b][a]=c; } sum=0; vec.clear(); prim(1); bool ans=false; for(int i=1;i<=N;i++){ if(ans)break; for(int j=1;j<=N;j++){ if(mp[i][j]!=-1){ if(sum-mx[i][j]+mp[i][j]==sum){ ans=true;break; } // else printf("mx[%d][%d]=%d\n",i,j,mx[i][j]); } } } if(ans)puts("Yes"); else puts("No"); } return 0; }
标签:
原文地址:http://www.cnblogs.com/handsomecui/p/5236122.html