求高人指点:wikioi 2171 棋盘覆盖

死活只有90分,到底哪里有问题。

题目地址:http://www.wikioi.com/problem/2171/

 

代码如下:

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
int m,n,tt,ww,map[102][102];
bool pd[102][102];
int zz=0,head[10102];
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
int h[10102],ans=0;
struct bian
{int to,nx,v;} e[100100];
void insert(int x,int y,int z)
{
	zz++; e[zz].to=y; e[zz].v=z; e[zz].nx=head[x]; head[x]=zz;
	zz++; e[zz].to=x; e[zz].v=z; e[zz].nx=head[y]; head[y]=zz;
}
bool check(int x,int y)
{
	if(x<1||x>n||y<1||y>n||pd[x][y]) return false;
	else return true;
}
void jiantu()
{
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	   {if((i+j)%2==0&&!pd[i][j])
	       {for(int k=0;k<4;k++)
		       {if(check(i+xx[k],j+yy[k]))
			       insert(map[i][j],map[i+xx[k]][j+yy[k]],1);
			   }  
		   }
	   }
}
void chai()
{
	tt=0,ww=(n*n+1)>>1;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	   {if(!pd[i][j])
	       {if((i+j)%2==0) {tt++; map[i][j]=tt;}
		    else {ww++; map[i][j]=ww;}
		   }
	   }
}
bool bfs()
{
	int q[10101],t=0,w=1;
	memset(h,-1,sizeof(h));
	q[0]=0; h[0]=0;
	while(t<w)
	   {int p=q[t],i;
	    i=head[p]; t++;
	    while(i)
	       {if(e[i].v&&h[e[i].to]<0)
		       {h[e[i].to]=h[p]+1; q[w]=e[i].to; w++;}
		    i=e[i].nx;
		   }
	   }
	if(h[n*n+1]==-1) return false;
	return true;
}
int dfs(int w,int f)
{
	if(w==n*n+1) return f;
	int i=head[w], used=0, rest;
	while(i)
	   {if(e[i].v&&h[e[i].to]==h[w]+1)
	       {rest=f-used;
		    rest=dfs(e[i].to,min(rest,e[i].v));
		    e[i].v-=rest;
		    e[i+1].v+=rest;
		    used+=rest;
		    if(used==f) return f;
		   }
	    i=e[i].nx;
	   }
	if(!used) h[w]=-1;
	return used;
}
void dinic()  {while(bfs()) ans+=dfs(0,0x7fffffff);}
int main()
{
	scanf("%d%d",&n,&m);
	if(m!=0)
	   {int x,y;
		for(int i=1;i<=m;i++)
		   {scanf("%d%d",&x,&y); pd[x][y]=true;}
	   }
	chai();
	for(int i=1;i<=tt;i++) insert(0,i,1);
	for(int i=((n*n+1)>>1)+1;i<=ww;i++) insert(i,n*n+1,1);
	jiantu();
	dinic();
	printf("%d",ans);
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值