专栏文章

题解:AT_abc412_d [ABC412D] Make 2-Regular Graph

AT_abc412_d题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miozcxwm
此快照首次捕获于
2025/12/03 03:37
3 个月前
此快照最后确认于
2025/12/03 03:37
3 个月前
查看原文

解法

首先可以发现,每一个所有节点度数都为 22 的图一定是循环图。
循环图最小节点数为 33,故整幅图最多只能分为两个循环图。
分情况讨论。

分为单独一部分

观察到题目中的 n8n\leq8,可以枚举每一个可能的循环图。
由于节点数一样,我们只需要枚举所有可能的顺序,再取所有答案中的最小值即可。

分为两部分

沿用上面的思路,我们可以先枚举第一部分的大小,再将整个顺序列表分为一二两部分继续求答案即可。

代码

CPP
#include <bits/stdc++.h>
#define int long long
const int N = 100;
const int Mod = 1e9 + 7;
using namespace std;
int n, m;
bool g[N][N], tg[N][N];
inline void solve(vector<int> vec, int st, int ed)
{
    for (int i = st; i <= ed; i++)
    {
        int nxt = vec[i == ed ? st : i + 1];
        int pre = vec[i == st ? ed : i - 1];
        tg[vec[i]][nxt] = 1;
        tg[nxt][vec[i]] = 1;
        tg[vec[i]][pre] = 1;
        tg[pre][vec[i]] = 1;
    }
}
inline int get()
{
    int cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cnt += tg[i][j] != g[i][j];
        }
    }
    return cnt / 2;
}
inline void clear()
{
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            tg[i][j] = 0;
        }
    }
}
signed main()
{
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        g[u][v] = 1;
        g[v][u] = 1;
    }
    vector<int> vec;
    for (int i = 1; i <= n; i++)
    {
        vec.push_back(i);
    }
    int mi = 1e9;
    do
    {
        // 1 个圈
        clear();
        solve(vec, 0, n - 1);
        mi = min(mi, get());
        // 2 个圈
        for (int i = 3; i <= n - 3; i++)
        {
            clear();
            solve(vec, 0, i - 1);
            solve(vec, i, n - 1);
            mi = min(mi, get());
        }
    } while (next_permutation(vec.begin(), vec.end()));
    cout << mi;
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...