[小清新] [AGC028C] Min Cost Cycle
posted on 2024-05-27 05:23:21 | under | source
转化 \(+\) 鸽巢原理。
由于一条边价值是 \(\min\),且答案求的也是 \(\min\)。考虑放开限制,计入一些非法情况但不影响答案,方便计算。
对此题而言,将 \(x,y\) 取最小看成 \(x,y\) 中选恰好一个即可。
那么问题得到简化。思考一个点 \(a_i,b_i\) 是否被计入答案(对答案贡献),不妨用 \(00,01,10,11\) 表示。
注意到一个关键性质,若不存在 \(11\),则不可能同时出现 \(01,10\)。
理由如下:将 \(x,y\) 的选择看成不同方向的有向边,由于这是一个环,所以必然存在一个 \(01,10\) 的交界点,这个交界点就是 \(11\) 了。同理,还能发现 \(00\) 与 \(11\) 成对出现(虽然没啥用)。
所以合法情况只有:只选 \(a\)、只选 \(b\)、选至少一对 \(a,b\)。前两种容易解决,考虑第三种。
可以利用鸽巢原理,具体如下:让所有 \(a,b\) 一起升序排列,选取前 \(n+1\) 个记为 \(c_1\dots c_{n+1}\),此时必然存在一对 \(a,b\)。
然后依次枚举去掉 \(c_{n-1},c_n,c_{n+1}\) 的方案是否满足条件,显然肯定有一种方案合法。
请注意,去掉 \(c_{n-1}\) 不一定是第三小方案,需要再枚举去掉 \(c_{n},c_{n+1}\) 然后加上 \(c_{n+2}\) 的方案。我不幸被坑了。
会影响正确性吗?不会,因为这是前 \(4\) 小的方案,而且根据先前讨论,其中必有一种合法,所以没毛病。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
int n, m, res, sa, sb, ans, a[N], b[N], buc[N];
pair<int, int> c[N];
inline void add(int p) {++buc[c[p].second], res += c[p].first;}
inline void del(int p) {--buc[c[p].second], res -= c[p].first;}
inline void check() {for(int i = 1; i <= n; ++i) if(buc[i] == 2) ans = min(ans, res);}
signed main(){
cin >> n;
for(int i = 1; i <= n; ++i){
scanf("%lld%lld", &a[i], &b[i]);
sa += a[i], sb += b[i];
c[++m] = {a[i], i}, c[++m] = {b[i], i};
}
ans = min(sa, sb), sort(c + 1, c + 1 + m);
for(int i = 1; i <= n + 1; ++i) add(i);
for(int i = n - 1; i <= n + 1; ++i) del(i), check(), add(i);
del(n), del(n + 1), add(n + 2), check();
cout << ans;
return 0;
}

浙公网安备 33010602011771号