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

来源:互联网 发布:星际老男孩淘宝店2016 编辑:程序博客网 时间:2024/04/30 05:21

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 0x7fffffffusing namespace std;const int N = 405;int n,m,cnt=1,T,ans;int last[N*N],map[N][N],num,h[N*N],q[N*N],nb[N][N];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;}
阅读全文
0 0
原创粉丝点击