CF875F Royal Questions 基环树Kruskal
Posted itst
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF875F Royal Questions 基环树Kruskal相关的知识,希望对你有一定的参考价值。
题目传送门:http://codeforces.com/problemset/problem/875/F
题意:有$N$个王子和$M$个公主,每个公主或王子都只能选择至多一个王子或公主作为自己的结婚对象(王子选择公主,公主选择王子不然还怎么选)。每个公主有且仅有两个中意的王子$a,b$,她只会至多选择其中一个作为自己的结婚对象,而如果某个公主选择了自己的结婚对象,就会给出$w$的嫁妆。求在满足所有公主的条件的情况下能够给出的最大嫁妆。$N,M leq 2 imes 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的主要内容,如果未能解决你的问题,请参考以下文章
CF875FRoyal Questions 最小生成基环树森林