一个图为二分图的充要条件就是不存在奇环。
先求出一个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;
}