#include using namespace std; const int N = 1010, M = 1e6 + 10; // 链式前向星 int e[M], h[N], idx, w[M], ne[M]; void add(int a, int b, int c = 0) { e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; } int g[N][N]; // 记录任意两个节点之间的憎恨关系 int n, m; // n个节点,m个关系,本题不是m条边,因为建的是补图 int color[N]; // 黑白染色法标识的颜色 int st[N]; // 是不是点双中的节点 int res[N]; // 标识数组,出现在奇数环的点双中,就是1,没有出现过就是0 // 二分染色法 int dfs(int u, int fa) { for (int i = h[u]; ~i; i = ne[i]) { int v = e[i]; if (v == fa || !st[v]) continue; // 必须是点双里的点,才能搜索,要不你搜索的就不对啦,看明白这个st数组的意义的吧~ if (color[v] == -1) { // 如果v点未染色 color[v] = color[u] ^ 1; // 反向黑白染色 if (dfs(v, u)) return 1; // 继续探索v节点,如果v节点完成后,发现了冲突,则u也汇报冲突 } else if (color[v] != (color[u] ^ 1)) // 如果已染色,并且,存在染色冲突 return 1; // 报告冲突 } return 0; } // Tarjan算法,求点双 int dfn[N], low[N], stk[N], top, ts; vector bcc[N]; int bcnt; void tarjan(int u, int fa) { dfn[u] = low[u] = ++ts; stk[++top] = u; for (int i = h[u]; ~i; i = ne[i]) { int v = e[i]; if (!dfn[v]) { tarjan(v, u); low[u] = min(low[u], low[v]); if (low[v] >= dfn[u]) { // 出现点双 // 业务需要,初始化临时变量数组 memset(st, 0, sizeof st); // 一个点双一清空,防止误判 memset(color, -1, sizeof color); // 黑白染色的标识数组也清空 // 利用栈内元素弹出,可以获取此环中有哪些节点,对节点标识已访问,并且计数 int x; bcnt++; do { x = stk[top--]; bcc[bcnt].push_back(x); st[x] = 1; } while (x != v); // 将子树出栈 bcc[bcnt].push_back(u); // 把割点/树根也丢到点双里 st[u] = 1; // 将当前点双之中的全部打上标记 color[u] = 0; // u标识为黑色,0:黑,1:白 // 二分图染色 // ① 环中节点数量必须大于等于3 // ② 二分图染色存在冲突=>是奇数环 // ③ 无向图进行黑白染色,必须设置fa参数,防止走回头路 // ④ 枚举每个点双中的节点,标识已节点出现在奇数环中 if (bcc[bcnt].size() >= 3 && dfs(u, -1)) for (int i : bcc[bcnt]) res[i] = 1; } } else low[u] = min(low[u], dfn[v]); } } int main() { #ifndef ONLINE_JUDGE freopen("SP2878.in", "r", stdin); #endif while (scanf("%d %d", &n, &m) && m + n) { memset(g, 0, sizeof g); // 多组测试数据,每次清空憎恨数组 memset(h, -1, sizeof h); // 初始化链式前向星 idx = 0; memset(dfn, 0, sizeof dfn); // Tarjan算法要测试多轮,清空数组【时间戳数组】 memset(low, 0, sizeof low); // Tarjan算法要测试多轮,清空数组【回溯祖先数组】 memset(res, 0, sizeof res); // 清空是否在奇数环中的标识数组 // 读入m条憎恨关系,注意:不要直接建图!因为最终的摆放方式不是憎恨的相邻摆放,而是不憎恨的相邻摆放! while (m--) { int a, b; scanf("%d %d", &a, &b); g[a][b] = g[b][a] = 1; } // 建立补图 for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) // i