AGC035B

adam01發表於2024-08-03

如果邊數為奇數,一定無解。

如果邊數為偶數,一定有解。考慮證明:

我們可以先隨便定向,然後給每個點 \(i\) 一個值 \(a_i\in\{0,1\}\),表示出邊條數奇偶性。

然後隨便考慮圖的一顆生成樹。

注意到一條邊 \((u,v)\) 翻轉定向會讓 \(a_u\gets 1-a_u,a_v\gets 1-a_v\)

這等於把 \(1\) 從邊的一段移動到另一端,碰上了就消掉。

有很多這種套路的,比如

  • 這道。
  • abc155_f Perils in Parallel
  • CF1994F Stardew Valley

透過貪心滿足孩子節點,一定可以構造出一種邊定向的方案。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1e5 + 5, M = 2e5 + 5;
int m, n;

int deg[N];
bool ch[M], vis[N];
vector<pair<int, int>> e[N];
void dfs(int x, int fa)
{
    vis[x] = 1;
    for(auto [i, id] : e[x])
    {
        if(vis[i]) continue;
        dfs(i, x);
        if(deg[i])
        {
            deg[x] ^= 1;
            ch[id] = 0;
        }
    }
}

int u[M], v[M];
signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= m; i ++)
    {
        int x, y; cin >> x >> y;
        ch[i] = 1;
        u[i] = x, v[i] = y;
        e[x].push_back({y, i});
        e[y].push_back({x, i});
        deg[x] ^= 1;
    }
    dfs(1, 0);
    if(deg[1]) return cout << -1, 0;
    for(int i = 1; i <= m; i ++)
        if(ch[i]) cout << u[i] << " " << v[i] << "\n";
        else cout << v[i] << " " << u[i] << "\n";

    return 0;
}

構造生成樹可以用並查集,也可以直接 dfs 搜。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1e5 + 5, M = 2e5 + 5;
int m, n;

int fa[N];
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}

int deg[N];
bool ch[M];
vector<pair<int, int>> e[N];
void dfs(int x, int fa)
{
    for(auto [i, id] : e[x])
    {
        if(i == fa) continue;
        dfs(i, x);
        if(deg[i])
        {
            deg[x] ^= 1;
            ch[id] = 0;
        }
    }
}

int u[M], v[M];
signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i ++) fa[i] = i;
    for(int i = 1; i <= m; i ++)
    {
        int x, y; cin >> x >> y;
        u[i] = x, v[i] = y;
        ch[i] = 1;
        deg[x] ^= 1;
        if(find(x) == find(y)) continue;
        e[x].push_back({y, i});
        e[y].push_back({x, i});
        fa[find(x)] = find(y);
    }
    dfs(1, 0);
    if(deg[1]) return cout << -1, 0;
    for(int i = 1; i <= m; i ++)
        if(ch[i]) cout << u[i] << " " << v[i] << "\n";
        else cout << v[i] << " " << u[i] << "\n";

    return 0;
}