【bzoj 2668】: [cqoi2012]交換棋子


http://www.lydsy.com/JudgeOnline/problem.php?id=2668


網絡流。
注意拆點的技巧
開始拆點的時候沒有注意點的出入關係,產生了“傳遞性”,導致混亂

理清楚關係:
限制的是交換次數
交換次數=sum{交換邊流量}
所以所有的交換邊連向一個點來限制次數

媽呀還是不對

點流量限制不用再拆點,只需要分類討論一下就可以了。。。。。。


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
////////////////////////////////////////////////
const int inf=0x3f3f3f3f;
const int N=1000;
const int M=10000;
int n,m,cnt1;
char beg[25][25],end[25][25],lim[25][25];
int A[25][25],B[25][25],tot;
int dx[]={1,-1,0,0,1,1,-1,-1};
int dy[]={0,0,1,-1,-1,1,-1,1};
int S,T;
struct edge{int v,f,c,next;}e[M];
int head[N],k;
int d[N],q[N*100],vis[N],clk;
////////////////////////////////////////////////
void adde(int u,int v,int f,int c){e[k]=(edge){v,f,c,head[u]};head[u]=k++;}
void ins(int u,int v,int f1,int f2,int c){adde(u,v,f1,c);adde(v,u,f2,-c);}
bool judge()
{
	int cnt=0;
	rep(i,1,n) rep(j,1,m) cnt+=beg[i][j]=='1';
	cnt1=cnt;
	rep(i,1,n) rep(j,1,m) cnt-=end[i][j]=='1';
	return cnt==0;
}
bool spfa()
{
	static bool inq[N]; MS(d,inf); d[q[0]=S]=0;
	for(int u,v,l=0,r=1;l<r;)
	{
		u=q[l++]; inq[u]=0;
		INE(i,u) if(e[i].f)
		    if(d[v=e[i].v]>d[u]+e[i].c)
		    {
		    	d[v=e[i].v]=d[u]+e[i].c;
		    	if(!inq[v]) inq[q[r++]=v]=1;
		    }
	}
	return d[T]<inf;
}
int dfs(int u,int a)
{
	vis[u]=clk;
	if(u==T) return a;
	INE(i,u) if(e[i].f && vis[e[i].v]!=clk && d[e[i].v]==d[u]+e[i].c)
	    if(int t=dfs(e[i].v,min(a,e[i].f)))
	        return e[i].f-=t,e[i^1].f+=t,t;
	return 0;
}
pair<int,int> zkw()
{
	int f=0,c=0;
	while(spfa()) do
	{
		int t=dfs(S,inf);
		f+=t; c+=t*d[T];
	}while(vis[T]==clk++);
	return make_pair(f,c);
}
////////////////////////////////////////////////
void input()
{
	MS(head,-1);
	n=read(); m=read();
	rep(i,1,n) scanf("%s",beg[i]+1);
	rep(i,1,n) scanf("%s",end[i]+1);
	rep(i,1,n) scanf("%s",lim[i]+1);
}
void solve()
{
	if(!judge())
	{
		puts("-1");
		return;
	}
	rep(i,1,n) rep(j,1,m) A[i][j]=++tot;
	rep(i,1,n) rep(j,1,m) B[i][j]=++tot;
	S=0; T=++tot;
	rep(i,1,n) rep(j,1,m)
	{
		int flag=0;
		if(beg[i][j]=='1') ins(S,A[i][j],1,0,0),flag++;
		if(end[i][j]=='1') ins(B[i][j],T,1,0,0),flag++;
		ins(A[i][j],B[i][j],flag+lim[i][j]-'0'>>1,0,1);
		rep(k,0,7)
		{
			int nx=i+dx[k],ny=j+dy[k];
			if(nx<1 || nx>n || ny<1 || ny>m) continue;
			ins(B[i][j],A[nx][ny],inf,0,0);
		}
	}
	pair<int,int> ret=zkw();
	if(ret.first!=cnt1)
	{
		puts("-1");
		return;
    }
	printf("%d\n",ret.second-cnt1);
}
////////////////////////////////////////////////
int main()
{
    freopen("C.in","r",stdin); freopen("C.out","w",stdout);
    input(),solve();
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章