网络流最小割 王者之剑

  传送门

    不用考虑走的方法,因为一旦合法,即不同时取相邻的两个,一定能达到。

    所以只用考虑怎么取就行了。

    把棋盘黑白染色,S到黑点建权值为val的边,白点到T建权值为val的边,

    然后把相邻的黑白点建一条为inf的边。

    求最小割。

    不得不提一句:边从零开始建和从一开始建一个wa一个a。。

                              ^时相应的正边和反边必须对应。(卡了好久,身败名裂

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#define inf 100000000
using namespace std;
int n,m,a[505][505],b[505][505],S=0,T,cnt,c[505][505];
int dep[100005],e,adj[100005],sum=0;
struct node
{
	int v,l,next;
} lu[100005];
void add(int u,int v,int l)
{lu[e].v=v;lu[e].l=l;lu[e].next=adj[u];adj[u]=e++;}
inline int bfs()
{
	memset(dep,0,sizeof(dep));
	queue<int> q;
	dep[S]=1;
	q.push(S);
	while(!q.empty())
	{
	    int x=q.front();q.pop();
	    for(int i=adj[x];i!=-1;i=lu[i].next)
	    {
	    	 int to=lu[i].v; 
	         if(lu[i].l&&!dep[to])
	         {
	         	  dep[to]=dep[x]+1;
	         	  q.push(to);
	         	  if(to==T)return 1;
			 }
		}
	}
	return 0;
}
inline int read()
{
    int su=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch<='9'&&ch>='0'){su=su*10+ch-'0';ch=getchar();}     
    return su;
}
inline int dfs(int now,int f){
	if(now==T){
		return f;
	}
	int tmp=f;
	for(int i=adj[now];i!=-1;i=lu[i].next){
		int to=lu[i].v,w=lu[i].l;
		if(w&&tmp&&dep[to]==dep[now]+1){
			int k=dfs(to,min(w,tmp));
			if(!k){
				dep[to]=0;
				continue;
			}
			lu[i].l-=k;
			lu[i^1].l+=k;
			tmp-=k;
		}
	}
	return f-tmp;
}
int yjn()
{
    freopen("Excalibur.in","r",stdin);
    freopen("Excalibur.out","w",stdout);
  	scanf("%d%d",&n,&m);
	memset(adj,-1,sizeof(adj));
	for(int i=1;i<=n;i++)
	{
	   int k=0;
	   if(i&1)k=1;
	   for(int j=1;j<=m;j++)
	   {
	   	  a[i][j]=++cnt;
		  b[i][j]=k;k^=1;
	      c[i][j]=read();
	      sum+=c[i][j];
		}
	}
/*	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		   cout<<b[i][j]<<" ";
		cout<<endl;
	}*/
	T=cnt+3;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
	  {
		if(b[i][j])
		  {add(a[i][j],T,c[i][j]),add(T,a[i][j],0);}
		else
		  {add(S,a[i][j],c[i][j]),add(a[i][j],S,0);}
      }
	for(int i=1;i<=n;i++)
	   for(int j=1;j<=m;j++)
	   {
	   	    if(b[i][j]==0)
	   	    {
	   	    	if(i!=1){add(a[i][j],a[i-1][j],inf),add(a[i-1][j],a[i][j],0);}
	   	    	if(i!=n){add(a[i][j],a[i+1][j],inf),add(a[i+1][j],a[i][j],0);}
	   	    	if(j!=1){add(a[i][j],a[i][j-1],inf),add(a[i][j-1],a[i][j],0);}
				if(j!=m){add(a[i][j],a[i][j+1],inf),add(a[i][j+1],a[i][j],0);}
			}
	   }
	int ans=0;
	while(bfs())
	    ans+=dfs(S,inf);
	cout<<(sum-ans);
}
int qty=yjn();
int main(){;}

posted @ 2017-10-06 20:19  Hzoi_QTY  阅读(170)  评论(0编辑  收藏  举报