[贪心] P9088 「SvR-2」1+2=3
posted on 2024-06-04 06:12:22 | under | source
菜鸡看完官方题解后恍然大悟,有感而发。
首先 \((0,0)\) 就是个 fw,排除它计算就好。
能产生贡献的配对无非只有:\((?,1)\to (2,?)\)、\((?,2)\to (1,?)\)。
考虑其中一种形式,看起来像是个二分图匹配,应当是两边的点集大小取 \(\min\)。
但是若有 \((2,1)\) 这种同时算作二分图两个点集的,就可能会影响答案,不妨让 \((2,1)\) 向对面点集连一条虚边,不能选但是可用来判断是否有环。
那么只会在全都是 \((2,1)\) 时必然出现环、多算 \(1\)。对于其它情况,可以让最后一个 \((2,1)\) 向其它数对连边,避免成环。\((1,2)\) 同理。
所以应该得到若干条链,将它们首尾相连即可。那么最后答案就是两种形式的和。
但是,这样还是可能出现环!若每个木棒的左右都有对应匹配(即答案为非 \((0,0)\) 数对之和),那么必然构成环,而且可以证明这是唯一一种有环的方案(类比前面构造)。于是答案会多算 \(1\),记得特判。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int T, a[3][3], sm, ans;
signed main(){
cin >> T;
while(T--){
sm = 0;
for(int i = 0; i < 3; ++i)
for(int j = 0; j < 3; ++j) scanf("%lld", &a[i][j]), sm += a[i][j];
int cnt1 = a[0][1] + a[1][1] + a[2][1], cnt2 = a[2][0] + a[2][1] + a[2][2];
int _cnt1 = a[0][2] + a[1][2] + a[2][2], _cnt2 = a[1][0] + a[1][1] + a[1][2];
ans = min(cnt1, cnt2) + min(_cnt1, _cnt2);
if(cnt1 == a[2][1] && cnt2 == a[2][1] && cnt1) --ans;
if(_cnt1 == a[1][2] && _cnt2 == a[1][2] && _cnt1) --ans;
if(ans && sm - a[0][0] == ans) --ans;
printf("%lld\n", ans);
}
return 0;
}

浙公网安备 33010602011771号