Party(图)

65 阅读2分钟

Problem - 1711B - Codeforces

题目描述

现在有一个聚会需要邀请一些成员,每个成员有一个不开心值。

现在共有 n(1n1e5)n(1\le n\le 1e5) 名成员,其中有 k(1k1e5)k(1\le k\le 1e5) 对朋友,现在让你邀请一些成员,要求被邀请的成员中朋友的对数是偶数,在此前提下,统计未被邀请的成员的不开心值之和的最小值。

需要解决 tt 组用例。

题目分析

这是一道 图上的思维题

首先我们假设邀请了所有成员,并统计其中朋友的对数,若这个对数的值为偶数,则不需要删除任何成员,即最终答案为 00

若对数值为奇数,我们可以从以下两种情况考虑。

第一种,只删除一个人。我们枚举所有成员,若当前成员与 mm 名其他成员互为朋友且 mm 为奇数,则将其删去会使最终朋友对数为偶数,我们只需要统计这类成员不开心值的最小值作为答案即可。

第二种,删除一对朋友,这两人均满足与其他 mm 名成员互为朋友,包括彼此。这样的话相当于删除了奇数对朋友,最终答案为这类朋友对不开心值得最小值。

我们可以证明以上两种情况必能产生最优解,因为若删除了 33 名及以上成员并使前提成立,都可以分成第一种和第二种情况的叠加而不优于两种情况的最优解。

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;
}