n (≤1000) 位騎士,m (≤10⁶) 對互相仇恨關係。圓桌會議規則:
無法參加任何合法會議的騎士須被開除。求開除人數。
一個無向圖中,點 u 能參與某個奇環 ⇔ u 所在的**雙連通分量**是**非二分圖**(即包含奇環)。
const int MAXN = 1005;
vector G[MAXN], bcc[MAXN];
stack> S;
int dfn[MAXN], low[MAXN], bccno[MAXN], dfs_clock, bcc_cnt;
bool iscut[MAXN];
void dfs(int u, int fa) {
dfn[u] = low[u] = ++dfs_clock;
int child = 0;
for (int v : G[u]) {
if (!dfn[v]) {
S.push({u,v});
child++;
dfs(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u]) {
iscut[u] = true;
bcc_cnt++;
while (true) {
auto e = S.top(); S.pop();
if (bccno[e.first] != bcc_cnt) { bcc[bcc_cnt].push_back(e.first); bccno[e.first]=bcc_cnt; }
if (bccno[e.second] != bcc_cnt) { bcc[bcc_cnt].push_back(e.second); bccno[e.second]=bcc_cnt; }
if (e.first==u && e.second==v) break;
}
}
} else if (dfn[v] < dfn[u] && v != fa) {
low[u] = min(low[u], dfn[v]);
S.push({u,v});
}
}
if (fa == -1 && child == 1) iscut[u] = false;
}
bool is_bipartite(const vector& comp) {
unordered_map color;
queue q;
for (int u : comp) if (!color.count(u)) {
color[u] = 0; q.push(u);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : G[u]) {
if (bccno[v] != bccno[u]) continue; // 只看分量內部邊
if (!color.count(v)) { color[v] = color[u]^1; q.push(v); }
else if (color[v] == color[u]) return false;
}
}
}
return true;
}