N 個騎士,M 對互相憎恨關係。圓桌會議要求:(1) 憎恨者不相鄰 (2) 參會人數為奇數。無法參加任何合法會議的騎士將被開除。求開除人數。
// Tarjan 求點雙連通分量
void dfs(int u, int fa) {
low[u] = dfn[u] = ++tot;
for (int v = 1; v <= n; v++) if (edge[u][v] && u != v) {
if (!vis[v]) {
vis[v] = 1;
sta[++cnt] = {u, v};
dfs(v, u);
low[u] = min(low[u], low[v]);
if (dfn[u] <= low[v]) {
// 彈出棧中邊形成一個分量
sum++;
do {
cur = sta[cnt--];
bcc[sum][cur.u] = bcc[sum][cur.v] = 1;
} while (!(cur.u==u && cur.v==v));
bcc[sum][u] = bcc[sum][v] = 1;
}
} else if (v != fa) {
low[u] = min(low[u], dfn[v]);
}
}
}
// 交叉染色檢測奇環
void color(int u, int c, int bcc_id) {
if (flag) return;
for (int v = 1; v <= n; v++) if (edge[u][v] && in_bcc[bcc_id][v]) {
if (vis[v] != -1) {
if (vis[v] == c) flag = 1;
} else {
vis[v] = c ^ 1;
color(v, c ^ 1, bcc_id);
}
}
}
點雙連通分量中,若存在一個奇環,則該分量內所有頂點都位於某個奇環上。因此只需對每個分量整體判斷是否含奇環,無需逐點檢查。