魏迟燕的自走棋
作者:互联网
魏迟燕的自走棋
题意
有 \(n\) 个人,\(m\) 件装备,每个人只能装备一件装备,每件装备只能分配给一个人。
其中,第 \(i\) 件装备可以给 \(k_i\) 个人中的一个,分别为 \(p_1,...,p_{k_i}\) 获得的战力提升为 \(w_i\) ,总战力提升即为所有士兵战力提升之和。
魏迟燕想知道他能获得的最大总战力提升为多少?
数据范围:\(1≤n,m≤1e5,1≤k_i≤2,1≤p_i≤n,1≤wi≤1e9\)
思路
因为价值只与装备有关,所以可以先按价值排序(从大到小),然后用匈牙利算法找到最大匹配量就相当于找到了最大权匹配,算法中要求每用一个新的装备进行匹配时都要清空vis数组(主要用于判断装备是否可以进行重新匹配),但是由于本题装备最多只有两个选择,所以可以确定如果为了匹配新装备而改变原来装备的匹配对象而失败时进行重新匹配的原装备就失去了重新匹配的能力,所以本题就没必要去清空vis数组,只用清空那些匹配成功的装备即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+1;
struct node {
long long k, a[3], c;
bool operator< (const node n1) {
return c > n1.c;
}
}p[maxn];
int match[maxn];
bool vis[maxn];
bool dfs(int x) {
for(int i = 1; i <= p[x].k; ++ i) {
int j = p[x].a[i];
if (vis[j]) continue;
vis[j] = true;
if (!match[j] || dfs(match[j])) {
match[j] = x;
vis[j] = false;
return true;
}
}
return false;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
for(int i = 1; i <= m; ++ i) {
cin >> p[i].k;
for(int j = 1; j <= p[i].k; ++ j) {
cin >> p[i].a[j];
}
cin >> p[i].c;
}
sort(p+1, p+m+1);
for(int i = 1; i <= m; ++ i) {
dfs(i);
}
long long res = 0;
for(int i = 1; i <= n; ++ i) {
if (match[i]) res += p[match[i]].c;
}
cout << res << "\n";
return 0;
}
标签:魏迟燕,匹配,int,装备,战力,maxn,走棋,bool 来源: https://www.cnblogs.com/yycx/p/14420380.html