修路方案 【最小生成树变形】-- 次小生成树

来源:互联网 发布:2017淘宝入门基础知识 编辑:程序博客网 时间:2024/05/22 16:55

修路方案

时间限制: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)
样例输入
23 31 2 12 3 23 1 34 41 2 22 3 23 4 24 1 2
样例输出
NoYes
 
来源
POJ题目改编
上传者

张云聪


模板题目

思路 算法核心思想:在prime求MST的过程中 用数组存储MST里面任意两点间的唯一的路中 权值最大的那条边的权值。最后枚举不在MST里面的边<i,,j>,判断<i,j>的权值 是否 和 MST里面 i 到 j 的最大权值相等,只要有一条边满足就可以说明MST不唯一。(因为我们可以用这条不在MST的边来 代替 在MST的边,这样MST肯定不唯一)

时间复杂度  citys*2


代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stack>
#include<vector>
#define inf 0x3f3f3f  //  次小生成树 
#define M 500+10
using namespace std;
int dis[M];
int map[M][M];
int v[M];  //以上的prime算法 都有 
int mst[M][M];  //mst中i和j的最大边权值 
int inmst[M][M]; //标记这个边是不是在mst中 
int pre[M]; // 记录前驱 
int citys,roads;
void getmap()
{
for(int i=1;i<=citys;i++)
{
for(int j=1;j<=citys;j++)
{
if(i==j) map[i][j]=0;
else map[i][j]=map[j][i]=inf;
}
}

for(int i=0;i<roads;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(map[a][b]>c)
map[a][b]=map[b][a]=c;
}
}
void solve ()
{
int min,next,sum=0;
memset(mst,0,sizeof(mst));
memset(inmst,0,sizeof(inmst));
for(int i=1;i<=citys;i++)
{
pre[i]=1;//  设置前驱

dis[i]=map[1][i];
v[i]=0; 
}
v[1]=1;
for(int u=2;u<=citys;u++)
{
min=inf; next=-1;
for(int j=1;j<=citys;j++)
{
if(!v[j]&&dis[j]<min)
{
min=dis[j];
next=j;
}
}
sum+=min;
v[next]=1;

int fa=pre[next];// 获得前驱 
inmst[fa][next]=inmst[next][fa]=1;  //在mst中 
for (int j=1;j<=citys;j++)
{
if(v[j]&&j!=next) //mst中的点 
mst[j][next]=mst[next][j]=max(mst[fa][j],dis[next]);

if(!v[j]&&dis[j]>map[j][next]) 

dis[j]=map[j][next];  //  更新距离 
pre[j]=next;  //  更新前驱
}

}
}
//  判断mst是不是唯一的
for(int i=1;i<=citys;i++)
{
for(int j=1;j<i;j++)
if(map[i][j]!=inf&&!inmst[i][j])
{
if(map[i][j]==mst[i][j])
{
printf("Yes\n");
return ;
}
}
}
printf("No\n"); 
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&citys,&roads);
getmap();
solve();

return 0;
}


0 0