南阳118--修路方案(次小生成树)

修路方案

时间限制: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题目改编
次小生成树, 判断MST是否唯一 。
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 501 
using namespace std;
int n, m;
const int INF = 0x3f3f3f3f;
int pre[N], Map[N][N];  //记录前趋和MST中最长边; 
int map[N][N], dis[N], vis[N]; 
bool INMST[N][N];       //判断边是否在MST中。 
void init(){
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            map[i][j]=(i==j?0:INF);
}
void Prime(){
    memset(vis, 0, sizeof(vis));
    memset(Map, 0, sizeof(Map)); 
    memset(INMST, false, sizeof(INMST));
    for(int i = 1; i <= n; i++){
        dis[i] = map[1][i];
        pre[i] = 1;
    }
    dis[1] = 0; vis[1] = 1;
    for(int i = 1; i < n; i++){
        int temp = 1, min = INF;
        for(int j = 1; j <= n; j++){
            if(!vis[j] && dis[j] < min){
                min = dis[j];
                temp = j;
            }
        } 
        if(min == INF)
            return;
        vis[temp] = 1;
        INMST[temp][pre[temp]]=INMST[pre[temp]][temp]=true;    //记录边在MST中; 
        for(int j = 1; j <= n; j++){
            if(vis[j] && j != temp)
                Map[j][temp] = Map[temp][j] = max(dis[temp], Map[pre[temp]][j]);
            if(!vis[j] && dis[j] > map[temp][j]){
                dis[j] = map[temp][j];        
                pre[j] = temp;   //更新前趋; 
            }
        }
    } 
}
void Solve(){
    bool flag = false;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j < i; j++){
            if(Map[i][j] != INF &&  !INMST[i][j] && Map[i][j] == map[i][j])   //存在边并且不在MST中,并且MST中边可以被替换;  
                flag = true; 
        } 
    if(flag)
        printf("Yes
");
    else
        printf("No
");
}
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        init();
        for(int i = 0; i < m; i++){
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            map[a][b]=map[b][a]=c;
        }
        Prime();
        Solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/soTired/p/5020854.html