1. 程式人生 > >Codeforces Round #535 F-MST Unification

Codeforces Round #535 F-MST Unification

clas names con return str ide ret def c++

題目大意:

給定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\n",ans-(n-1)); /// 去掉唯一的的MST所需的n-1條邊 } return 0; }
View Code

Codeforces Round #535 F-MST Unification