HDU 6311 Cover——欧拉路径

版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/81227184

题意:

给你一个图,问你最少几次一笔画可以画完

思路:

将同一连通块中的每对奇数点连边,跑出欧拉路径后断开刚才连的边,剩下的边就是结果

注意细节,首先判掉孤立点,然后注意有奇数点的时候别全连了,留两个,毕竟我们跑的是欧拉路径而不是欧拉回路,没奇数点的时候就随便跑了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e5 + 10;
struct Edge {
    int from, to, id, vis;
};
vector<Edge> edges;
vector<int> G[maxn];
int degree[maxn];
bool vis[maxn];
vector<int> point;
vector<int> ac;
int res;
vector<int> ans[maxn];

void init(int n) {
    edges.clear();
    for (int i = 0; i <= n; i++) G[i].clear();
    for (int i = 0; i <= n; i++) degree[i] = 0;
    for (int i = 0; i <= n; i++) vis[i] = false;
    res = 0;
    for (int i = 0; i <= n; i++) ans[i].clear();
}
void addedge(int from, int to, int id) {
    edges.push_back(Edge{from, to, id, 0});
    edges.push_back(Edge{to, from, -id, 0});
    int sz = edges.size();
    G[from].push_back(sz-2);
    G[to].push_back(sz-1);
    degree[from]++;
    degree[to]++;
}
void dfs1(int u) {
    vis[u] = true;
    if (degree[u] & 1) point.push_back(u);
    for (int i = 0; i < G[u].size(); i++) {
        Edge &e = edges[G[u][i]];
        if (!vis[e.to]) dfs1(e.to);
    }
}
void dfs2(int u) {
    for (int i = 0; i < G[u].size(); i++) {
        Edge &e = edges[G[u][i]];
        if (e.vis) continue;
        e.vis = edges[G[u][i]^1].vis = true;
        dfs2(e.to);
        ac.push_back(e.id);
    }
}

int main() {
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        init(n);
        int u, v;
        for (int i = 1; i <= m; i++) {
            scanf("%d%d", &u, &v);
            addedge(u, v, i);
        }
        for (int i = 1; i <= n; i++) {
            if (vis[i] || degree[i] == 0) continue;
            point.clear();
            dfs1(i);
            for (int j = 2; j < point.size(); j += 2) addedge(point[j], point[j+1], 0);
            ac.clear();
            int t = (point.empty() ? i : point[0]);
            dfs2(t);
            for (int j = ac.size() - 1; j >= 0; j--) {
                if (ac[j] == 0) continue;
                res++;
                while (ac[j] != 0 && j >= 0) {
                    ans[res].push_back(ac[j]);
                    j--;
                }
                j++;//没用
            }
        }
        printf("%d\n", res);
        for (int i = 1; i <= res; i++) {
            printf("%d", ans[i].size());
            for (int j = 0; j < ans[i].size(); j++) {
                printf(" %d", ans[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}

 

阅读更多
换一批

没有更多推荐了,返回首页