1. 程式人生 > >CF875F Royal Questions 基環樹、Kruskal

CF875F Royal Questions 基環樹、Kruskal

.html 而且 ++ def fin ext time lan 匹配

題目傳送門:http://codeforces.com/problemset/problem/875/F

題意:有$N$個王子和$M$個公主,每個公主或王子都只能選擇至多一個王子或公主作為自己的結婚對象(王子選擇公主,公主選擇王子不然還怎麽選)。每個公主有且僅有兩個中意的王子$a,b$,她只會至多選擇其中一個作為自己的結婚對象,而如果某個公主選擇了自己的結婚對象,就會給出$w$的嫁妝。求在滿足所有公主的條件的情況下能夠給出的最大嫁妝。$N,M \leq 2 \times 10^5 , w \leq 10^4$


很像帶權二分圖最大匹配,然而用KM或者費用流復雜度難以保證,考慮使用其他算法。

我們將王子作為點,某一個公主對應的兩個王子之間連一條邊,邊權為公主的嫁妝,那麽我們的題目變成了:選擇若幹條邊,使得每條邊只匹配其中一個端點(某個公主選擇其中一個王子)的情況下不匹配重復的端點(王子選擇一個公主),而且邊權最大。於是本題與棋盤上的守衛變為相同的模型。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define MAXN 200010
 4 using namespace std;
 5 
 6 struct Edge{
 7     int start , end , w;
 8 }Ed[MAXN];
 9 int A , B , fa[MAXN];
10 bool vis[MAXN];
11 
12 bool operator <(Edge a , Edge b){
13     return a.w > b.w;
14 }
15 
16 int find(int
x){ 17 return fa[x] == x ? x : (fa[x] = find(fa[x])); 18 } 19 20 int main(){ 21 ios::sync_with_stdio(0); 22 cin.tie(0); 23 cout.tie(0); 24 int A , B , ans = 0; 25 cin >> A >> B; 26 for(int i = 1 ; i <= B ; i++) 27 cin >> Ed[i].start >> Ed[i].end >> Ed[i].w;
28 for(int i = 1 ; i <= A ; i++) 29 fa[i] = i; 30 sort(Ed + 1 , Ed + B + 1); 31 for(int i = 1 ; i <= B ; i++){ 32 int p = find(Ed[i].start) , q = find(Ed[i].end); 33 if(p == q){ 34 if(!vis[p]){ 35 vis[p] = 1; 36 ans += Ed[i].w; 37 } 38 } 39 else 40 if(!(vis[p] && vis[q])){ 41 fa[q] = p; 42 vis[p] |= vis[q]; 43 ans += Ed[i].w; 44 } 45 } 46 cout << ans; 47 return 0; 48 }

CF875F Royal Questions 基環樹、Kruskal