本题其实考察了一个基础知识:
可以将图的结点用两种颜色染色,满足相邻点不同色的图,称为二分图。而在不满足二分图构成条件的图里,一定可以找到一个简单奇环。
在明确这一点的基础上,就可以使用dfs对图结构进行染色。在dfs的过程中,用栈保存点结构的遍历信息,从而检索出现奇数环的情况。
#include <bits/stdc++.h>
#define sc(x) scanf("%d", &(x))
#define pr(x) printf("%d ", x)
using namespace std;
typedef long long ll;
const int N = 5e5 + 7;
const ll mod = 1e9 + 7;
int to[N << 1], nxt[N << 1], head[N], tot;
inline void add(int u, int v) {
to[++tot] = v;
nxt[tot] = head[u];
head[u] = tot;
}
int n, m;
bool color[N], err;
int st[N], pos[N], p;
void dfs(int x, int fa, bool c) {
if (!err && pos[x] && pos[x] < p && (pos[x] - p) % 2 == 0) {
err = 1;
printf("%d\n", p - pos[x] + 1);
for (int i = pos[x]; i <= p; ++i) printf("%d ", st[i]);
}
if (err || pos[x]) return;
st[++p] = x, pos[x] = p;
color[x] = c;
for (int i = head[x]; i; i = nxt[i])
if (to[i] != fa) dfs(to[i], x, !c);
--p;
}
int main() {
sc(n), sc(m);
for (int i = 0, u, v; i < m; ++i) {
sc(u), sc(v);
add(u, v), add(v, u);
}
dfs(1, 0, 0);
if (!err) {
puts("0");
for (int i = 1; i <= n; ++i) printf("%d ", color[i]);
}
return 0;
} 附上注释
#include <bits/stdc++.h>
#define sc(x) scanf("%d", &(x))
#define pr(x) printf("%d ", x)
using namespace std;
typedef long long ll;
const int N = 5e5 + 7;
const ll mod = 1e9 + 7;
int to[N << 1], nxt[N << 1], head[N], tot;
inline void add(int u, int v) {
to[++tot] = v;
nxt[tot] = head[u];
head[u] = tot;
}
int n, m;
bool color[N], err;
int st[N], pos[N], p;
void dfs(int x, int fa, bool c) {
if (!err && pos[x] && pos[x] < p && (pos[x] - p) % 2 == 0) { //出现奇环
//由于上述的等价性,奇数环的判定条件
//(pos[x] - p) % 2 == 0可换成color[x]!=c
err = 1;
printf("%d\n", p - pos[x] + 1);
for (int i = pos[x]; i <= p; ++i) printf("%d ", st[i]);
}
if (err || pos[x]) return; //如果出现奇环或者此节点已经访问过
st[++p] = x, pos[x] = p; //入栈 用桶存栈中下标
color[x] = c; //染色
for (int i = head[x]; i; i = nxt[i])
if (to[i] != fa) dfs(to[i], x, !c);
--p;
}
int main() {
sc(n), sc(m);
for (int i = 0, u, v; i < m; ++i) {
sc(u), sc(v);
add(u, v), add(v, u);
}
dfs(1, 0, 0);
if (!err) {
puts("0");
for (int i = 1; i <= n; ++i) printf("%d ", color[i]);
}
return 0;
} 
京公网安备 11010502036488号