BZOJ1443: [JSOI2009]遊戲Game
阿新 • • 發佈:2019-01-15
強連通 rst int online name != oid scanf front
傳送門
這個博弈類似放骨牌,參見這道題
所以就可以黑白染色之後跑二分圖最大匹配,其中的不必匹配的點就是答案
這些點是什麽呢,\(yy\) 一下發現貌似就是殘余網絡中與 \(s\) 或 \(t\) 在同一個強連通分量的點?
# include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn(10005); const int maxm(1e6 + 5); int first[maxn], id[105][105], n, m, cnt, idx, lev[maxn], cur[maxn]; int dfn[maxn], low[maxn], dfx, st[maxn], tp, vis[maxn], bel[maxn], mark[maxn]; queue <int> q; char mp[105][105]; struct Edge { int to, next, w; } edge[maxm]; inline void Add(int u, int v, int w) { edge[cnt] = (Edge){v, first[u], w}, first[u] = cnt++; edge[cnt] = (Edge){u, first[v], 0}, first[v] = cnt++; } inline int Bfs() { int e, u, v; memset(lev, 0, sizeof(lev)); lev[0] = 1, q.push(0); while (!q.empty()) { u = q.front(), q.pop(); for (e = first[u]; ~e; e = edge[e].next) if (!lev[v = edge[e].to] && edge[e].w) lev[v] = lev[u] + 1, q.push(v); } return lev[idx + 1]; } int Dfs(int u, int maxf) { if (u == idx + 1) return maxf; int ret, &e = cur[u], v, f; for (ret = 0; ~e; e = edge[e].next) if (lev[v = edge[e].to] == lev[u] + 1 && edge[e].w) { f = Dfs(v, min(edge[e].w, maxf - ret)); ret += f, edge[e].w -= f, edge[e ^ 1].w += f; if (ret == maxf) break; } if (!ret) lev[u] = 0; return ret; } void Tarjan(int u) { low[u] = dfn[u] = ++dfx, st[++tp] = u, vis[u] = 1; int e, v; for (e = first[u]; ~e; e = edge[e].next) if (edge[e].w) { if (!dfn[v = edge[e].to]) Tarjan(v), low[u] = min(low[u], low[v]); else if (vis[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { do { v = st[tp--], vis[v] = 0; bel[v] = u; } while (v ^ u); } } int main() { memset(first, -1, sizeof(first)); int i, j, e, v, ans; scanf("%d%d", &n, &m), ans = 0; for (i = 1; i <= n; ++i) { scanf(" %s", mp[i] + 1); for (j = 1; j <= m; ++j) id[i][j] = ++idx; } for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mp[i][j] != '#' && (~(i + j) & 1)){ Add(0, id[i][j], 1); if (mp[i - 1][j] == '.') Add(id[i][j], id[i - 1][j], 1); if (mp[i + 1][j] == '.') Add(id[i][j], id[i + 1][j], 1); if (mp[i][j - 1] == '.') Add(id[i][j], id[i][j - 1], 1); if (mp[i][j + 1] == '.') Add(id[i][j], id[i][j + 1], 1); } else if (mp[i][j] != '#') Add(id[i][j], idx + 1, 1); while (Bfs()) memcpy(cur, first, sizeof(cur)), Dfs(0, 1e9); for (i = 0; i <= idx + 1; ++i) if (!dfn[i]) Tarjan(i); ans = 0; for (e = first[0]; ~e; e = edge[e].next) if (bel[v = edge[e].to] == bel[0]) mark[v] = 1; for (e = first[idx + 1]; ~e; e = edge[e].next) if (bel[v = edge[e].to] == bel[idx + 1]) mark[v] = 1; for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mark[id[i][j]]) ++ans; ans ? puts("WIN") : puts("LOSE"); for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mark[id[i][j]]) printf("%d %d\n", i, j); return 0; }
BZOJ1443: [JSOI2009]遊戲Game