Description
你有一个
n
个点
对于每条边,判断删除之后是否为二分图。
n,m≤104
Solution
一个图是二分图当且仅当没有奇环。
对
dfs
树黑白染色,如果一条返祖边两端的颜色一样就说明是奇环。
发现如果有一个偶环也覆盖了这条边,那么删除这条边之后这个偶环和原来的奇环会形成一个奇环。
显然一条边合法必须所有奇环都经过这条边。
所以对偶环打上
−1
标记,奇环打上
+1
标记,如果一条边的标记和是奇环个数那么就合法。
所以实际上是
O(n+m)
的。。。。
#include <bits/stdc++.h>
using namespace std;
const int N = 10101;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
struct edge {
int to, next;
edge(int t = 0, int n = 0): to(t), next(n) {}
};
edge G[N << 1];
int head[N], dep[N], tag[N], pre[N], tag1[N], vis[N];
int n, m, Gcnt, x, y, ont, dfc;
vector<int> ans;
inline void AddEdge(int from, int to) {
G[++Gcnt] = edge(to, head[from]); head[from] = Gcnt;
G[++Gcnt] = edge(from, head[to]); head[to] = Gcnt;
}
inline void dfs1(int u, int f, int d) {
dep[u] = d; pre[u] = ++dfc; int to;
for (int i = head[u]; i; i = G[i].next) {
to = G[i].to; if (to == f) continue;
if (pre[to] && pre[to] < pre[u]) {
if (dep[u] ^ dep[to]) { // even circles
--tag[u]; ++tag[to]; --tag1[i >> 1];
} else {
++tag[u]; --tag[to]; ++tag1[i >> 1]; ++ont;
}
} else if (!pre[to]) dfs1(to, u, d ^ 1);
}
}
inline int dfs2(int u, int f) {
int to, t1, t = tag[u]; vis[u] = 1;
for (int i = head[u]; i; i = G[i].next) {
to = G[i].to; if (to == f) continue;
if (pre[to] < pre[u]) {
if (tag1[i >> 1] == ont) ans.push_back(i >> 1);
} else if (!vis[to]) {
t1 = dfs2(to, u); t += t1;
if (t1 == ont) ans.push_back(i >> 1);
}
}
return t;
}
int main(void) {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
read(n); read(m); Gcnt = 1;
for (int i = 1; i <= m; i++) {
read(x); read(y);
AddEdge(x, y);
}
for (int i = 1; i <= n; i++)
if (!pre[i]) dfs1(i, 0, 1);
for (int i = 1; i <= n; i++)
if (!vis[i]) dfs2(i, 0);
sort(ans.begin(), ans.end());
if (!ont) {
ans.clear();
for (int i = 1; i <= m; i++) ans.push_back(i);
}
printf("%d\n", ans.size());
for (int x: ans) printf("%d ", x);
return 0;
}