骑士共存问题(二分图最大独立集)

//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;
}

  

posted @ 2017-02-18 12:08  vwirtveurit  阅读(176)  评论(0编辑  收藏  举报