【COGS 2051】王者之剑 最小割

这个其实就是在说明相邻的点不能取,我们发现只要其满足这个条件他总能走出来,那么我们就最小割就是了,我们先黑白染色,S 一排黑点 一排白点 T 对于相邻的点我们就直接中间连INF,于是就满足只要一个点选了,另一个点就不能选,我们跑完最小割就得到了满足相邻的点要么都选要么只选一方的最下舍弃。

#include <cstdio>
#include <cstring>
#define r register
#define Inf 0x7f7f7f7f
using namespace std;
inline int read()
{
   r int sum=0;
   r char ch=getchar();
   while(ch<'0'||ch>'9')ch=getchar();
   while(ch>='0'&&ch<='9')
   {
     sum=(sum<<1)+(sum<<3)+ch-'0';
     ch=getchar();
   }
   return sum;
}
int a[105][105],S,T,n,m;
struct  Via
{
  int to,next,f;
}c[200000];
int head[100000],t=1;
inline void add(int x,int y,int z)
{
  c[++t].to=y;
  c[t].f=z;
  c[t].next=head[x];
  head[x]=t;
}
inline int Min(int x,int y)
{
  return x<y?x:y;
}
int q[20000],top,tail,deep[20000];
inline bool bfs()
{
  memset(deep,0,sizeof(deep));
  deep[S]=top=tail=1,q[1]=S;
  while(top<=tail)
  {
    r int x=q[top++];
    if(x==T)return 1;
    for(r int i=head[x];i;i=c[i].next)
    if(c[i].f&&deep[c[i].to]==0)
    {
      deep[c[i].to]=deep[x]+1;
      q[++tail]=c[i].to;
    }
  }
  return 0;
}
int dfs(int x,int v)
{
  if(x==T||!v)return v;
  r int ret=0;
  for(r int i=head[x];i;i=c[i].next)
  if(c[i].f&&deep[c[i].to]==deep[x]+1)
  {
    r int f=dfs(c[i].to,Min(v,c[i].f));
    v-=f,ret+=f,c[i].f-=f,c[i^1].f+=f;
    if(!v)break;
  }
  if(!ret)deep[x]=0;
  return ret;
}
inline int dinic()
{
  r int ans=0;
  while(bfs())ans+=dfs(S,Inf);
  return ans;
}
int main()
{
  freopen("Excalibur.in","r",stdin);
  freopen("Excalibur.out","w",stdout);
  n=read(),m=read();
  r int ans=0;
  S=n*m+1,T=S+1;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
      a[i][j]=read(),ans+=a[i][j];
      if((i+j)&1)
      {
        add(S,(i-1)*m+j,a[i][j]),add((i-1)*m+j,S,0);
        if(i!=1)add((i-1)*m+j,(i-2)*m+j,Inf),add((i-2)*m+j,(i-1)*m+j,0);
        if(j!=1)add((i-1)*m+j,(i-1)*m+j-1,Inf),add((i-1)*m+j-1,(i-1)*m+j,0);
        if(i!=n)add((i-1)*m+j,i*m+j,Inf),add(i*m+j,(i-1)*m+j,0);
        if(j!=m)add((i-1)*m+j,(i-1)*m+j+1,Inf),add((i-1)*m+j+1,(i-1)*m+j,0);
      }
      else
      {
        add((i-1)*m+j,T,a[i][j]),add(T,(i-1)*m+j,0);
      }
    }
  printf("%d",ans-dinic());
}

 

posted @ 2017-08-05 08:43  TS_Hugh  阅读(246)  评论(0编辑  收藏  举报