骑士共存问题(网络流24题之一)

                                                                                          题目

题目描述

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

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

输入输出格式

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

输出格式:
将计算出的共存骑士数输出

 

思路分析:这一题……也没啥好讲的了,都把图画了出来色都染了,还有什么意思……不过还是要讲讲di

首先,我们按照颜色把图分成两部分,然后把互相攻击的连边,跑一遍最大流,然后用总的点数 - 障碍物的数量 - 最大流就是最终的答案。。

讲的有点草率,如果还是不理解的话可以看看这篇blog讲得比较详细。

代码:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1000005;
const int MAXM=1000005;
int d[MAXN],n,m,p[MAXN],eid,S,T,x,y;
struct A{
	int v,c,next;
}e[MAXM];
void init(){
	memset(p,-1,sizeof(p));
	eid=0;
}
void add(int u,int v,int c){
	e[eid].v=v;
	e[eid].c=c;
	e[eid].next=p[u];
	p[u]=eid++;
}
void insert(int u,int v,int c){
	add(u,v,c);
	add(v,u,0);
}
int bfs(){
	memset(d,-1,sizeof(d));
	queue<int>q;
	d[S]=0;
	q.push(S);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=p[u];i!=-1;i=e[i].next){
			int v=e[i].v;
			if(e[i].c>0&&d[v]==-1){
				d[v]=d[u]+1;
				q.push(v);	
			}
		}
	}
	return (d[T]!=-1);
}
int dfs(int u,int flow){ 
	if(u==T) return flow;
	int ret=0;
	for(int i=p[u];i!=-1;i=e[i].next){
		int v=e[i].v;
		if(e[i].c>0&&d[v]==d[u]+1){
			int tmp=dfs(v,min(flow,e[i].c));
			e[i].c-=tmp;
			e[i^1].c+=tmp;
			flow-=tmp;
			ret+=tmp;
			if(!flow) break;
		}
	}
	if(!ret) d[u]=-1;
	return ret;
}
int Dinic(){
	int ret=0;
	while(bfs()){
		ret+=dfs(S,INF);
	}
	return ret;
}                       //以上部分是标准的Dinic,这里就不多讲
int a[MAXN];
int main () {
	init();
	scanf("%d%d", &n,&m);
	S=0;T=n*n+1;
	for(int i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		a[(x-1)*n+y]=1;    //把二维转换成一维的
	}
	for(int i=1;i<=n*n;i++)if(!a[i])  
	{
		if(((i+n-1)/n+(i-1)%n+1)%2){ //下面这一大坨嘛……只可意会不可言传
        insert(S,i,1);
		if(i-2*n-1>0&&i-2*n-1<=n*n&&i>2*n&&i%n!=1) insert(i,i-2*n-1,INF);
		if(i-2*n+1>0&&i-2*n+1<=n*n&&i>2*n&&i%n) insert(i,i-2*n+1,INF);
		if(i+2*n-1>0&&i+2*n-1<=n*n&&i<=(n-2)*n&&i%n!=1) insert(i,i+2*n-1,INF);
		if(i+2*n+1>0&&i+2*n+1<=n*n&&i<=(n-2)*n&&i%n) insert(i,i+2*n+1,INF);
		if(i-1*n-2>0&&i-1*n-2<=n*n&&i>n&&i%n!=1&&i%n!=2) insert(i,i-1*n-2,INF);
		if(i-1*n+2>0&&i-1*n+2<=n*n&&i>n&&i%n!=0&&i%n!=n-1) insert(i,i-1*n+2,INF);
		if(i+1*n-2>0&&i+1*n-2<=n*n&&i<=(n-1)*n&&i%n!=1&&i%n!=2) insert(i,i+1*n-2,INF);
		if(i+1*n+2>0&&i+1*n+2<=n*n&&i<=(n-1)*n&&i%n!=0&&i%n!=n-1) insert(i,i+1*n+2,INF);
		}else
		insert(i,T,1);
		}
	printf("%d",n*n-Dinic()-m);//大家可以想想为蛤输出这个。。(相信大家都会的)
	return 0;
}

 

posted @ 2018-07-29 21:57  lahlah  阅读(27)  评论(0编辑  收藏  举报