P3355 騎士共存問題
阿新 • • 發佈:2018-10-27
問題 網絡流 就是 cst else include ges 這就是 二分
二分圖最大獨立集
先給出二分圖最大獨立集的概念:選擇最多的點,使任何邊的兩邊不被同時選中。
並且有結論:最大獨立集=節點總數-最大匹配。
這道題為什麽是二分圖?
我們可以通過\((x,y)\)中的\(x+y\)的奇偶性來構造二分圖,顯然它們肯定不會互相攻擊。
當一個點\(x+y\)為奇時,向它能攻擊到的點都連一條權值為1的邊。
這就是這個二分圖的建圖方法。
但是我不會匈牙利算法,直接網絡流套下去就行了。
註意:那些障礙點對我們整個計算根本沒有影響,直接忽略它們就可以了。節點總數也不用計算它們。
代碼:
#include<cstdio> #include<cstring> #include<algorithm> const int maxn = 205, maxN = 40005; const int INF = 0x3f3f3f3f; const int dx[] = {-1, 1, -2, 2, -2, 2, -1, 1}; const int dy[] = {-2, -2, -1, -1, 1, 1, 2, 2}; struct Edges { int next, to, weight; } e[4000005]; int head[maxN], tot = 1; bool b[maxn][maxn]; int dep[maxN], cur[maxN]; int queue[maxN << 1], front, rear; int n, m; int s, t; int cnt; int id(int x, int y) { return (x - 1) * n + y; } void link(int u, int v, int w) { e[++tot] = (Edges){head[u], v, w}; head[u] = tot; } void addEdges(int u, int v, int w) { link(u, v, w); link(v, u, 0); } bool bfs() { memset(dep, 0, sizeof dep); front = rear = 0; dep[s] = 1; queue[rear++] = s; while(front < rear) { int u = queue[front++]; for(int i = head[u]; i; i = e[i].next) { int v = e[i].to; if(e[i].weight > 0 && !dep[v]) { dep[v] = dep[u] + 1; queue[rear++] = v; } } } return dep[t]; } int dfs(int u, int flow) { if(u == t) return flow; for(int &i = cur[u]; i; i = e[i].next) { int v = e[i].to; if(e[i].weight > 0 && dep[v] == dep[u] + 1) { int di = dfs(v, std::min(flow, e[i].weight)); if(di > 0) { e[i].weight -= di; e[i ^ 1].weight += di; return di; } } } return 0; } int dinic() { int ans = 0; while(bfs()) { for(int i = 1; i <= t; i++) cur[i] = head[i]; while(int temp = dfs(s, INF)) ans += temp; } return ans; } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { int temp; scanf("%1d", &temp); b[i][j] = temp; if(temp) cnt++; } } s = n * n + 1, t = s + 1; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { if(b[i][j]) continue; if((i + j) % 2) { addEdges(s, id(i, j), 1); for(int k = 0; k < 8; k++) { int nx = i + dx[k], ny = j + dy[k]; if(nx >= 1 && nx <= n && ny >= 1 && ny <= n) { addEdges(id(i, j), id(nx, ny), 1); } } } else { addEdges(id(i, j), t, 1); } } } printf("%d\n", n * n - cnt - dinic()); return 0; }
P3355 騎士共存問題