2018 Multi-University Training Contest 2 - Cover

欧拉回路

最多几笔画完,显然和欧拉回路有关。。

我们可以把所有度数为奇数的点两两配对,最后会形成若干个全是偶数度数的联通块。

显然每个联通块都是欧拉回路。

然后我们dfs这些联通块,跑一次欧拉回路。

用数组模拟的邻接表存图后,首先访问的一定是后加的,我们可以利用这些边来将欧拉回路分段。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int X = 0, w = 0; char ch = 0;
    while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
inline int gcd(int a, int b){ return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}
const int N = 100005;
int n, m, cnt, head[N], d[N], tot;
bool vis[N], kills[N<<2];
struct Edge { int v, next, id; } edge[N<<2];
vector<int> p[N];

void build(){
    full(head, -1), full(d, 0);
    full(vis, false), full(kills, false);
    tot = cnt = 0;
    //for(int i = 1; i <= n; i ++) p[i].clear();
}

void addEdge(int a, int b, int id){
    edge[cnt].v = b, edge[cnt].id = id, edge[cnt].next = head[a], head[a] = cnt ++;
}

void dfs(int s){
    vis[s] = true;
    for(int i = head[s]; i != -1; i = edge[i].next){
        int u = edge[i].v;
        if(kills[i]) continue;
        kills[i] = kills[i^1] = true;
        dfs(u);
        if(edge[i].id) p[tot].push_back(-edge[i].id);
        else tot ++;
    }
}

int main(){

    FAST_IO;
    while(cin >> n >> m){
        build();
        for(int i = 1; i <= m; i ++){
            int u, v;
            cin >> u >> v;
            addEdge(u, v, i), addEdge(v, u, -i);
            d[u] ++, d[v] ++;
        }
        int t = 0;
        for(int i = 1; i <= n; i ++){
            if(t == 0 && (d[i] & 1)) t = i;
            else if(t && (d[i] & 1)){
                addEdge(t, i, 0), addEdge(i, t, 0);
                t = 0;
            }
        }
        for(int i = 1; i <= n; i ++){
            if((d[i] & 1) && !vis[i]){
                tot ++, dfs(i), tot --;
            }
        }
        for(int i = 1; i <= n; i ++){
            if(!vis[i] && d[i]) tot ++, dfs(i);
        }
        cout << tot << endl;
        for(int i = 1; i <= tot; i ++){
            cout << p[i].size();
            for(int j = 0; j < p[i].size(); j ++)
                cout << " " << p[i][j];
            cout << endl;
            p[i].clear();
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/onionQAQ/p/10903036.html