次小生成树+最小生成树是否唯一

TheUniqueMST
Description:
判断最小生成树是否唯一,如果唯一,输出最小代价和;如果不唯一,输出”NOT“。
思路:
①先生成一棵最小生成树,得到最小代价。
②然后扫描MST的每一条边,然后判读如果少了这一条边,再生成一棵树(也有可能无法生成,因为有些边是不可缺少的,需要判断),那么对这些新生成的树的代价和进行判断。即可生成次小生成树,判断MST是否唯一。

时间复杂度:O(m^2*log(m))

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#define ll long long
#define inf 100000008
#define mod 1000000007
using namespace std;

const int maxn=10000;  //数组要开够
int n,m,fa[105];
struct Edge{
    int u,v,cost;
}t[maxn];

bool cmp(Edge a,Edge b){
    return a.cost<b.cost;
}

int find(int x){
    return (x==fa[x])?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
    fa[find(x)]=find(y);
}

void init(){
    for(int i=1;i<=n;i++) fa[i]=i;
}

int ncase;
int main(){
    cin>>ncase;
    while(ncase--){
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            int u,v,cost;
            scanf("%d%d%d",&u,&v,&cost);
            t[i].u=u;t[i].v=v;t[i].cost=cost;
        }
        init();
        sort(t+1,t+m+1,cmp);
        int mct=0;
        vector<Edge> mst;
        for(int i=1;i<=m;i++){
            int u=t[i].u,v=t[i].v;
            if(find(u)!=find(v)){
                mct+=t[i].cost;
                merge(u,v);
                mst.push_back(t[i]);
            }
        }//生成了最小树
        
        bool flag=true;
        for(int i=0;i<mst.size();i++){
            init();
            int cnt=0;
            int sec_mct=0;
            for(int j=1;j<=m;j++){
                if(mst[i].u==t[j].u&&mst[i].v==t[j].v) continue;
                int u=t[j].u,v=t[j].v;
                if(find(u)!=find(v)){  //保证无环
                    sec_mct+=t[j].cost;
                    merge(u,v);
                    cnt++;
                }
            }
            //有些边是必不可少的边,一旦缺失,无法构成一棵树
            if(cnt==n-1&&sec_mct==mct){
                flag=false;
                break;
            }
        }
        if(flag) printf("%d\n",mct);
        else printf("Not Unique!\n");
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值