题目描述
现在有一个聚会需要邀请一些成员,每个成员有一个不开心值。
现在共有 名成员,其中有 对朋友,现在让你邀请一些成员,要求被邀请的成员中朋友的对数是偶数,在此前提下,统计未被邀请的成员的不开心值之和的最小值。
需要解决 组用例。
题目分析
这是一道 图上的思维题。
首先我们假设邀请了所有成员,并统计其中朋友的对数,若这个对数的值为偶数,则不需要删除任何成员,即最终答案为 。
若对数值为奇数,我们可以从以下两种情况考虑。
第一种,只删除一个人。我们枚举所有成员,若当前成员与 名其他成员互为朋友且 为奇数,则将其删去会使最终朋友对数为偶数,我们只需要统计这类成员不开心值的最小值作为答案即可。
第二种,删除一对朋友,这两人均满足与其他 名成员互为朋友,包括彼此。这样的话相当于删除了奇数对朋友,最终答案为这类朋友对不开心值得最小值。
我们可以证明以上两种情况必能产生最优解,因为若删除了 名及以上成员并使前提成立,都可以分成第一种和第二种情况的叠加而不优于两种情况的最优解。
Accept 代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t; cin >> t;
while (t --)
{
int n, k;
cin >> n >> k;
vector<int> w(n + 1), g(n + 1);
vector<pair<int, int>> p(k + 1);
for (int i = 1; i <= n; i ++) cin >> w[i];
int sum = 0;
for (int i = 1; i <= k; i ++)
{
int x, y;
cin >> x >> y;
g[x] ++, g[y] ++, sum ++;
p[i] = {x, y};
}
int res = (sum % 2 ? 1e9 : 0);
for (int i = 1; i <= n; i ++)
if (g[i] % 2) res = min(res, w[i]);
for (int i = 1; i <= k; i ++)
{
int x = p[i].first, y = p[i].second;
if ((g[x] + g[y] - 1) % 2) res = min(res, w[x] + w[y]);
}
cout << res << "\n";
}
return 0;
}