[贪心] 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;
}
posted @ 2026-01-13 11:20  Zwi  阅读(0)  评论(0)    收藏  举报