COGS 2051王者之剑 最小割
Posted TS_Hugh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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()); }
以上是关于COGS 2051王者之剑 最小割的主要内容,如果未能解决你的问题,请参考以下文章