P3355 骑士共存问题

\(\color{#0066ff}{题目描述}\)

在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入

对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击

\(\color{#0066ff}{输入格式}\)

第一行有 2 个正整数n 和 m (\(1<=n<=200, 0<=m<n^2\)),分别表示棋盘的大小和障碍数。接下来的 m 行给出障碍的位置。每行 2 个正整数,表示障碍的方格坐标。

\(\color{#0066ff}{输出格式}\)

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

\(\color{#0066ff}{输入样例}\)

3 2
1 1
3 3

\(\color{#0066ff}{输出样例}\)

5

\(\color{#0066ff}{数据范围与提示}\)

nothing

\(\color{#0066ff}{题解}\)

最大流等于最小割定理

合法情况下,总情况-不成立情况=成立情况

因为最小割等于最大流,所以找到不成立情况的最大流

就得到了答案

现在我们要找不合法情况的最大流

考虑上图的红黄点,一个红点被占据,只会影响黄点,黄点同理

因此,S向所有红点连容量为 1 的边

所用红点向其影响的黄点连容量为 inf 的边(保证被影响,求出所有不合法情况

所有黄点向T连容量为 1 的边

答案就是n*n-m-最大流

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define _ 0
#define LL long long
inline LL in()
{
    LL x=0,f=1; char ch;
    while(!isdigit(ch=getchar()))(ch=='-')&&(f=-f);
    while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
    return x*f;
}
const int inf=0x7fffffff;
struct node{int to,nxt,dis;}e[1050050];
int rx[]={-2,-2,-1,-1,1,1,2,2};
int ry[]={-1,1,-2,2,-2,2,-1,1};
int cnt=1,n,m,s,t;
std::queue<int> q;
int head[505005],cur[505005],dep[500505];
bool mp[250][250];
inline int getid(int x,int y) {return (x-1)*n+y;}
inline void add(int from,int to,int dis)
{
	cnt++;
	e[cnt].to=to;
	e[cnt].dis=dis;
	e[cnt].nxt=head[from];
	head[from]=cnt;
}
inline void expand(int x,int y)
{
	for(int i=0;i<8;i++)
	{
		int xx=x+rx[i];
		int yy=y+ry[i];
		if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&!mp[xx][yy])
		{
			add(getid(x,y),getid(xx,yy),inf);
			add(getid(xx,yy),getid(x,y),0);
		}
	}
}
inline bool bfs()
{
	for(int i=s;i<=t;i++) dep[i]=0,cur[i]=head[i];
	q.push(s);
	dep[s]=1;
	while(!q.empty())
	{
		int tp=q.front(); q.pop();
		for(int i=head[tp];i;i=e[i].nxt)
		{
			int go=e[i].to;
			if(!dep[go]&&e[i].dis>0)
			{
				dep[go]=dep[tp]+1;
				q.push(go);
			}
		}
	}
	return dep[t];
}
inline int dfs(int x,int change)
{
	if(x==t||!change) return change;
	int flow=0,ls;
	for(int i=cur[x];i;i=e[i].nxt)
	{
		int go=e[i].to;
		cur[x]=i;
		if(dep[go]==dep[x]+1&&(ls=dfs(go,std::min(change,e[i].dis))))
		{
			change-=ls;
			flow+=ls;
			e[i].dis-=ls;
			e[i^1].dis+=ls;
			if(!change) break;
		}
	}
	return flow;
}
inline int dinic()
{
	int flow=0;
	while(bfs()) flow+=dfs(s,inf);
	return flow;
}
int main()
{
	n=in(),m=in();
	t=n*n+1,s=0;
	int x,y;
	for(int i=1;i<=m;i++)
	{
		x=in(),y=in();
		mp[x][y]=true;
	}
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
	{
		if(mp[i][j]) continue;
		if((i+j)&1)
		{
			add(s,getid(i,j),1);
			add(getid(i,j),s,0);
			expand(i,j);
		}
		else add(getid(i,j),t,1),add(t,getid(i,j),0);
	}
	printf("%d",n*n-m-dinic());
	return 0;
}
posted @ 2018-12-11 14:13  olinr  阅读(164)  评论(0编辑  收藏  举报