1. 程式人生 > >Codeforces Round #535 (Div. 3) F

Codeforces Round #535 (Div. 3) F

define 題意 http 答案 def nod hid efi eve

F. MST Unification

題目傳送門

題意

給你n個頂點,m條邊;保證沒有重邊,其中存在多個MST(最小生成樹),

你可以修改一些邊的權值,讓其中有且僅有一個最小生成樹,求最少操作的邊數。

思路:

最小生成樹算法的加工,我們從kruskal算法入手,kruskal就是先對邊排序,

然後遍歷邊不斷加入一些合格邊來完善最小生成樹

那麽在這個過程中,如果邊的權值一樣的話,就會產生多種MST,但是這裏

不能僅僅只是累計相同權值的邊數,因為與合格邊相同權值的邊可能可以選擇

多條。

所以我們可以將所有符合的邊累加起來,然後減去(n-1)就是與合格邊沖突的邊

,也就是答案了

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
#define N 200005
int n,m;
struct node
{
    int u,v,w;
    bool operator <(const node &p) const{
      return w<p.w;
    }
}edge[N];
int fa[N];

int Find(int x)
{
    if(x==fa[x]) return x;
    else return fa[x]=Find(fa[x]);
}
int main() { while(~scanf("%d %d",&n,&m)) { for(int i=0;i<m;i++) scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w); for(int i=1;i<=n;i++) fa[i]=i; sort(edge,edge+m); int ans=0; int L=0; for(int i=0;i<m;i++) {
int u=edge[i].u,v=edge[i].v; u=Find(u),v=Find(v); if(u!=v) ans++; if(i+1<m && edge[i].w!=edge[i+1].w) { for(int j=L;j<=i;j++) { int u=edge[j].u,v=edge[j].v; u=Find(u),v=Find(v); if(u!=v) fa[u]=v; } L=i+1; } } printf("%d\n",ans-(n-1)); } }
View Code

Codeforces Round #535 (Div. 3) F