Codeforces Round #535 F-MST Unification

题目大意:

给定n m 为图中的点数n和边数m

给定m条边的信息 u v w 为u点到v点有一条长度为w的边

图中无环无重边

这个图的MST的花费为k 但可能存在多种花费为k的MST的方案

此时对图中的边进行操作 可增大权重或翻倍增大权重

要求只保留图中的一种花费为k的MST方案时 需要对最少多少条边进行操作

1.原本的kruskal 会选出构成MST的最短的n-1条边

即在n=5边长度为 1 2 2 3 4 4 5 6 的图中

原本会选出4条 1 2 3 4 (能构成1种MST的方案)

2.这个方法会记录到最短的n-1条边和与这些边长度相等的边

现在会选出6条 1 2 2 3 4 4 (能构成多种MST方案)

3.此时只保留一种MST方案的话需4条(n-1条)边

则需要对多出的6-4=2条边进行操作

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=2e5+5;
int n, m;
struct EDGE {
    int u,v,w;
    bool operator <(const EDGE& p)const {
        return w<p.w;
    }
}e[N];
int fa[N];
int getfa(int u) {
    if(fa[u]==u) return u;
    else return fa[u]=getfa(fa[u]);
}
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        for(int i=0;i<m;i++)
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sort(e,e+m);
        for(int i=1;i<=n;i++) fa[i]=i;
        int ans=0, L=0;
        for(int i=0;i<m;i++) {
            int u=getfa(e[i].u), v=getfa(e[i].v);
            if(u!=v) ans++;

            if(i+1<m and e[i+1].w!=e[i].w) {
                for(int j=L;j<=i;j++) {
                    u=getfa(e[j].u), v=getfa(e[j].v);
                    if(u!=v) fa[u]=v;
                }
                L=i+1;
            }
        }
        printf("%d
",ans-(n-1));
        /// 去掉唯一的的MST所需的n-1条边
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zquzjx/p/10312490.html