您的位置:首页 > 理论基础 > 计算机网络

[网络流24题][codevs1922] 骑士共存问题 二分图最大独立集

2017-05-19 11:15 465 查看

1922 骑士共存问题

题目描述 Description

在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘

上某些方格设置了障碍,骑士不得进入。



对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑

士,使得它们彼此互不攻击。

输入描述 Input Description

第一行有2 个正整数n 和m (1<=n<=200, 0<=m < n^2),

分别表示棋盘的大小和障碍数。接下来的m 行给出障碍的位置。每行2 个正整数,表示障

碍的方格坐标。

输出描述 Output Description

将计算出的共存骑士数输出

样例输入 Sample Input

3 2

1 1

3 3

样例输出 Sample Output

5

#include<iostream>
#include<cstring>
#include<cstdio>
#define INF 0x7fffffff
using namespace std;
const int N = 405;
int n,m,cnt=1,T,ans;
int last[N*N],map

,num,h[N*N],q[N*N],nb

;
int dx[8] = {1,1,2,2,-1,-1,-2,-2};
int dy[8] = {2,-2,1,-1,2,-2,1,-1};
struct Edge{
int to,v,next;
}e[N*N*4];
void insert( int u, int v, int w ){
e[++cnt].to = v; e[cnt].v = w; e[cnt].next = last[u]; last[u] = cnt;
e[++cnt].to = u; e[cnt].v = 0; e[cnt].next = last[v]; last[v] = cnt;
}
bool bfs(){
int head = 0, tail = 1;
memset(h,-1,sizeof(h));
q[0] = 0; h[0] = 0;
while( head != tail ){
int now = q[head++]; if( now == T ) return true;
for( int i = last[now]; i; i = e[i].next )
if( e[i].v && h[e[i].to] == -1 ){
h[e[i].to] = h[now] + 1;
q[tail++] = e[i].to;
}
}
return h[T] != -1;
}
int dfs( int x, int f ){
if( x == T ) return f;
int w,used = 0;
for( int i = last[x]; i; i = e[i].next )
if( e[i].v && h[e[i].to] == h[x] + 1 ){
w = dfs( e[i].to, min(f-used,e[i].v) );
e[i].v -= w; e[i^1].v += w; used += w;
if( used == f ) return used;
}
if( !used ) h[x] = -1;
return used;
}
void dinic(){
while(bfs()){
ans += dfs(0,INF);
}
}
void build(){
T = n*n+1;
for( int i = 1; i <= n; i++ ) for( int j = 1; j <= n; j++ ) nb[i][j] = ++num;
for( int i = 1; i <= n; i++ )
for( int j = 1; j <= n; j++ )
if( !map[i][j] ){
if( (i+j) % 2 == 0 ){
insert(0,nb[i][j],1);
for( int k = 0; k < 8; k++ ){
int xx = i + dx[k]; int yy = j + dy[k];
if( xx < 1 || xx > n || yy < 1 || yy > n || map[xx][yy] ) continue;
insert( nb[i][j], nb[xx][yy], 1 );
}
} else{
insert( nb[i][j], T, 1 );
}
}
}
int main(){
scanf("%d%d", &n, &m);
for( int i = 1, x, y; i <= m; i++ ) scanf("%d%d", &x, &y ), map[x][y] = 1;
build(); dinic();
printf("%d",n*n-m-ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: