骑士共存问题(二分图最大独立集)
//http://www.cnblogs.com/IMGavin/ #include <iostream> #include <stdio.h> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <map> #include <stack> #include <set> #include <bitset> #include <algorithm> using namespace std; typedef long long LL; #define gets(A) fgets(A, 1e8, stdin) const int INF = 0x3F3F3F3F, N = 50000, MOD = 1003, M = 1000000; int dir[8][2] = {{1, 2}, {1, -2},{-1, -2}, {-1, 2}, {2, 1}, {-2, 1},{-2, -1}, {2, -1}}; bool mp[210][210]; const double EPS = 1e-6; int head[N], tot; struct node{ int u, v, cap, next; }edge[M]; int cur[N], lev[N], s[N]; void init(){ memset(head, -1, sizeof(head)); tot = 0; } void add(int u, int v, int cap){ edge[tot].u = u; edge[tot].v = v; edge[tot].cap = cap; edge[tot].next = head[u]; head[u] = tot++; //反向弧 edge[tot].u = v; edge[tot].v = u; edge[tot].cap = 0; edge[tot].next = head[v]; head[v] = tot++; } bool bfs(int st, int des){ memset(lev, -1, sizeof(lev)); lev[st] = 0; queue<int> q; q.push(st); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap && lev[v] == -1){ lev[v] = lev[u] + 1; q.push(v); if(v == des){ return true; } } } } return false; } //源点,汇点,点的数量 int dinic(int st, int des, int n){ int ans = 0; while(bfs(st, des)){ memcpy(cur, head, sizeof(int) * (n + 1)); int u = st, top = 0; while(true){ if(u == des){ int mini = INF, loc; for(int i = 0; i < top; i++){ if(mini > edge[s[i]].cap){ mini = edge[s[i]].cap; loc = i; } } for(int i = 0; i < top; i++){ edge[s[i]].cap -= mini; edge[s[i] ^ 1].cap += mini; } ans += mini; top = loc; u = edge[s[top]].u; } int &i = cur[u];//引用类型 for(; i != -1; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap && lev[v] == lev[u] + 1){ break; } } if(i != -1){ s[top++] = i; u = edge[i].v; }else{ if(!top){ break; } lev[u] = -1; u = edge[s[--top]].u; } } } return ans; } int main(){ int n, m; while(cin >> n >> m){ memset(mp, 0, sizeof(mp)); for(int i = 0; i < m; i++){ int x, y; cin >> x >> y; mp[x][y] = 1; } init(); int st = 0, des = n *n + 1; for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ if(mp[i][j]){ continue; } if((i + j) % 2){ for(int k = 0; k < 8; k++){ int x = i + dir[k][0]; int y = j + dir[k][1]; if(x >= 1 && x <= n && y >= 1 && y <= n){ if(!mp[x][y]){ add((i - 1) * n + j, (x - 1) * n + y, INF); } } } add(st, (i - 1) * n + j, 1); }else{ add((i - 1) * n + j, des, 1); } } } printf("%d\n", n * n - m - dinic(st, des, des + 2)); } return 0; }