BZOJ 4424. Cf19E Fairy

一个图为二分图的充要条件就是不存在奇环。
先求出一个dfs树,然后考虑非树边对dfs树的影响。
有几种情况需要考虑。
一、不存在自环及奇环
都可以删。
二、自环
如果存在两个自环及以上,就不可能了,因为它只能删除一条边。
有一个自环,当不存在奇环的时候就只能删除这个自环,否则也没边可删了。
三、存在一个奇环
那么这个奇环上的树边及非树边都可以删。也只有这种情况能删非树边。
四、存在多个奇环
那么能删除的边就是这些奇环的树边的交集。同时,这个交集的边不能出现在偶环上,否则奇环+偶环还是会得到奇环。
那么树上差分一下得到每条边在多少个奇环上,如果在偶环上就把路径减一下,就能处理出不能在偶环上的情况。最后就判断一下每一条边的值是否为奇环的个数。

#include <bits/stdc++.h>

namespace IO {
    void read() {}
    template<class T, class... T2>
    void read(T &x, T2 &... oth) {
        x = 0; T f = 1; char ch = getchar();
        while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
        while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
        x *= f;
        read(oth...);
    }
}

const int N = 1e6 + 7;
struct E {
    int v, ne, id;
} e[N << 1];
int head[N], tag[N], dep[N], cnt = 1;
bool vis[N];
int self, n, m;

void add(int u, int v, int id) {
    e[++cnt].v = v; e[cnt].ne = head[u]; e[cnt].id = id; head[u] = cnt;
    e[++cnt].v = u; e[cnt].ne = head[v]; e[cnt].id = id; head[v] = cnt;
}

int tol, fei;

void dfs(int u, int f) {
    for (int i = head[u]; i; i = e[i].ne) {
        if (i == (f ^ 1)) continue;
        int v = e[i].v;
        if (dep[v]) {
            if (dep[v] > dep[u]) continue;
            if ((dep[u] - dep[v] + 1) & 1) {
                tol++;
                fei = e[i].id;
                tag[u]++; tag[v]--;
            } else {
                tag[u]--; tag[v]++;
            }
        } else {
            dep[v] = dep[u] + 1;
            dfs(v, i);
            tag[u] += tag[v];
        }
    }
}

std::vector<int> vec;

void dfs(int u) {
    vis[u] = 1;
    for (int i = head[u]; i; i = e[i].ne) {
        int v = e[i].v;
        if (vis[v]) continue;
        if (tag[v] == tol)
            vec.push_back(e[i].id);
        dfs(v);
    }
}

int main() {
    IO::read(n, m);
    for (int i = 1; i <= m; i++) {
        int u, v;
        IO::read(u, v);
        if (u == v && !self) {
            self = i;
            continue;
        }
        if (u == v) {
            self = -1;
            continue;
        }
        add(u, v, i);
    }
    if (self == -1) {
        puts("0");
        return 0;
    }
    for (int i = 1; i <= n; i++) {
        if (!dep[i])
            dep[i] = 1, dfs(i, 0);
    }
    if (tol == 0) {
        if (self) {
            printf("1\n%d\n", self);
        } else {
            printf("%d\n", m);
            for (int i = 1; i <= m; i++)
                printf("%d%c", i, " \n"[i == m]);
        }
        return 0;
    }
    if (self) {
        puts("0");
        return 0;
    }
    for (int i = 1; i <= n; i++)
        if (!vis[i])
            dfs(i);
    if (tol == 1)
        vec.push_back(fei);
    printf("%d\n", (int)vec.size());
    std::sort(vec.begin(), vec.end());
    for (int i = 0; i < vec.size(); i++)
        printf("%d%c", vec[i], " \n"[i + 1 == vec.size()]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/12283444.html