CF36E Two Paths 题解

分类讨论:设连通块数量为 $c$,奇数点数量为 $s$。

  1. $c > 2$ 时,不珂学。
  2. $c = 2$ 时,两个连通块分别跑欧拉路径。
  3. $c = 1$ 时,再分讨:
    • $s \not = 0,2,4$ 不珂学。
    • $s = 0,2$ 跑一遍欧拉路径。
    • $s = 4$ 连一条虚边, 跑一遍欧拉路径。
点击查看代码
#include<bits/stdc++.h>


using namespace std;
const int N = 1e4 + 500;

struct edge{
    int next, to, w, id;
} e[N << 1];

int n, m;
int head[N], cnt = 1;

void add(int f, int t, int i) {
    e[++cnt] = edge{head[f], t, 1, i}, head[f] = cnt;
    e[++cnt] = edge{head[t], f, 1, i}, head[t] = cnt;
}

vector<int> SCC[N];
int du[N], tot, d[N], r_in[N];
int st[N], top;

void pre_dfs(int u, int f) {
    if(!d[u]) SCC[tot].emplace_back(u);
    d[u] = tot;
    for(int i = head[u];i;i = e[i].next) {
        int v = e[i].to;
        if(v == f || d[v]) continue;
        pre_dfs(v, u);
    }
}

void dfs(int u) {
    for(int &i = head[u]; i; i = e[i].next) {
        int v = e[i].to, id = e[i].id;
        if(!e[i].w) continue;
        e[i].w = e[i ^ 1].w = 0;
        dfs(v);
        st[++top] = id;
    }
}

int main() {

    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);

    ios::sync_with_stdio(0);
    cin.tie(nullptr), cout.tie(nullptr);

    n = 1e4;
    cin >> m;
    int R_a = 0, R_b = 0;

    for(int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        if(!R_a) R_a = u, R_b = v;
        add(u, v, i);
        du[u]++, du[v]++;
        r_in[u] = r_in[v] = 1;
    }

    for(int i = 1; i <= n; ++i) if(r_in[i] && !d[i]) ++tot, pre_dfs(i, 0);
    // for(auto o : SCC[1]) cout << o << " "; cout << endl;
    // for(int i = 1; i <= n; ++i) if(r_in[i]) cout << du[i] << " "; cout << endl;

    if(tot >= 3) {cout << -1; return 0; } 
    else if(tot == 2) { 
        int id = SCC[1][0], cnt = 0;
        int id2 = SCC[2][0], cnt2 = 0;
        for(auto o : SCC[1]) 
            if(du[o] & 1) {
                id = o;
                cnt++;
            }
        for(auto o : SCC[2]) 
            if(du[o] & 1) {
                id2 = o;
                cnt2++;
            }
        
        if(cnt & 1 || cnt > 2) {cout << -1; return 0; }  
        if(cnt2 & 1 || cnt2 > 2) {cout << -1; return 0; }  
        dfs(id);cout << top << endl;
        for(int i = 1; i <= top; ++i) cout << st[i] << " ";
        cout << endl; top = 0;
        dfs(id2); cout << top << endl;
        for(int i = 1; i <= top; ++i) cout << st[i] << " ";
    }  else { 
        int id[5] = {0, 0, 0, 0, 0}, cnt = 0;
        for(auto o : SCC[1]) {
            if(du[o] & 1) {
                cnt++; int j = 0; 
                while(j < 4 && id[++j]);
                if(j <= 4 && !id[j]) id[j] = o; 
            }
        }
        
        if(cnt & 1 || cnt > 4) {cout << -1; return 0; }  
        if(!cnt || cnt == 2) {
            if(cnt) dfs(id[1]); 
            else dfs(SCC[1][0]);
            if(top == 1) {cout << -1; return 0; }  
            cout << top - 1 << endl;
            for(int i = 1; i < top; ++i) cout << st[i] << " ";
            cout << endl << 1 << endl << st[top];
        } else { 
           
            add(id[1], id[2], 114514);
            dfs(id[3]); 
            int j = 1; 
            vector<int> i1, i2;
            for(; j <= top; ++j) if(st[j] != 114514) i1.emplace_back(st[j]); else break; 
            for(; j <= top; ++j) if(st[j] != 114514) i2.emplace_back(st[j]); // 这里可能有危险
            cout << i1.size() << endl;
            for(auto o : i1) cout << o << " "; 
            cout << endl << i2.size() << endl;
            for(auto o : i2) cout << o << " ";
        }
    }
    return 0;
}
posted @ 2023-11-03 20:19  Saka_Noa  阅读(15)  评论(0)    收藏  举报  来源