洛谷P3355 骑士共存问题 二分图_网络流

Code:

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=800004;
const int INF=10000000;
int A[205][205],B[205][205];
int dy[]={-1,-2,-2,-1,1,2,2,1};
int dx[]={-2,-1,1,2,-2,-1,1,2};
# define  pb push_back
int s,t;
struct Edge{
	int from,to,cap;
	Edge(int u,int v,int c):from(u),to(v),cap(c) {}
};
struct Dicnic{
   vector<Edge>edges;
   vector<int>G[maxn];
   int d[maxn],vis[maxn],cur[maxn];
   queue<int>Q;
   void addedge(int u,int v,int c){
	edges.pb(Edge(u,v,c));               //正向弧
	edges.pb(Edge(v,u,0));               //反向弧
	int m=edges.size();
	G[u].pb(m-2);
	G[v].pb(m-1);
   }
   int BFS()
   {
	memset(vis,0,sizeof(vis));
	d[s]=0,vis[s]=1;Q.push(s);
	while(!Q.empty()){
		int u=Q.front();Q.pop();
		int sz=G[u].size();
		for(int i=0;i<sz;++i){
			Edge e=edges[G[u][i]];
			if(!vis[e.to]&&e.cap>0){
				d[e.to]=d[u]+1,vis[e.to]=1;
				Q.push(e.to);
			}
		}
	}
	return vis[t];
   }
   int dfs(int x,int a){
	   if(x==t)return a;
	   int sz=G[x].size();
	   int f,flow=0;
	   for(int i=cur[x];i<sz;++i){
		Edge e=edges[G[x][i]];
		cur[x]=i;
		if(d[e.to]==d[x]+1&&e.cap>0){
			f=dfs(e.to,min(a,e.cap));
			if(f)
			{
				int u=G[x][i];
				a-=f;
				edges[u].cap-=f;
				edges[u^1].cap+=f;
				flow+=f;
				if(a==0)break;
			}
		}
	   }
	   return flow;
   }
   int maxflow(){
	int ans=0;
	while(BFS()){
	  memset(cur,0,sizeof(cur));
	  ans+=dfs(s,INF);
	}
	return ans;
   }
}op;
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	int cnt=0;
	s=0;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j){
                                     A[i][j]=++cnt;
		}
	t=cnt*2+1;
	for(int i=1;i<=m;++i)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		B[a][b]=1;
	}
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=n;++j)
		{
			if(B[i][j])continue;
                                     for(int ii=0;ii<8;++ii)
                                     {
                                              int yy=dy[ii]+i,xx=dx[ii]+j;
                                                      if(yy>=1&&yy<=n&&xx>=1&&xx<=n)
                                                      	 if(!B[yy][xx])op.addedge(A[i][j],A[yy][xx]+cnt,INF);
                                     }
		}
	}
	for(int i=1;i<=n;++i)
	        for(int j=1;j<=n;++j)
	        {
	    	if(!B[i][j])op.addedge(s,A[i][j],1);
	    }
	for(int i=cnt+1;i<=cnt+cnt;++i)
	{
		op.addedge(i,t,1);
	}
	int ans=cnt-op.maxflow()/2;
	printf("%d\n",ans-m);
	return 0;
}

  

posted @ 2019-02-12 23:45  EM-LGH  阅读(130)  评论(0编辑  收藏  举报