Codeforces Round #535 F-MST Unification
阿新 • • 發佈:2019-01-24
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]; intView Codegetfa(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; }
Codeforces Round #535 F-MST Unification