方格取数(网络流24题)
Posted sto324
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方格取数(网络流24题)相关的知识,希望对你有一定的参考价值。
题意
在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
题解
方格是常见的二分图(疑问脸)。所以考虑先染色,相邻的格子颜色不同,这样就分成了二分图,先假设全选,然后跑最小割就好了,割掉就是不选。
#include<bits/stdc++.h> using namespace std; const int maxn=10005; const int maxm=40005; const int inf=1000009; int n,m,s,t,ans; int cnt=1,head[maxn]; struct edge int x,y,next,val; e[maxm<<1]; void add(int x,int y,int val) e[++cnt]=(edge)x,y,head[x],val; head[x]=cnt; void add_edge(int x,int y,int val) add(x,y,val); add(y,x,0); template<class T>inline void read(T &x) x=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48);ch=getchar(); int d[maxn]; bool bfs() memset(d,0,sizeof(d)); queue<int> q; q.push(s);d[s]=1; while(!q.empty()) int x=q.front(); q.pop(); for(int i=head[x];i;i=e[i].next) int y=e[i].y; if(e[i].val&&!d[y]) d[y]=d[x]+1; if(y==t) return true; q.push(y); return false; int dfs(int x,int flow) if(x==t) return flow; int rest=flow,k; for(int i=head[x];i;i=e[i].next) int y=e[i].y; if(e[i].val&&d[y]==d[x]+1) k=dfs(y,min(rest,e[i].val)); if(!k) d[y]=0; e[i].val-=k; e[i^1].val+=k; rest-=k; return flow-rest; int dinic() int res=0; while(bfs()) res+=dfs(s,0x3f3f3f); return res; int main() read(n);read(m); s=0;t=n*m+1; for(int i=1;i<=n;i++) int op=i&1; for(int j=1;j<=m;j++) int x;read(x); ans+=x; if(op) add_edge(s,(i-1)*m+j,x); if(i>1) add_edge((i-1)*m+j,(i-2)*m+j,inf); if(i<n) add_edge((i-1)*m+j,i*m+j,inf); if(j>1) add_edge((i-1)*m+j,(i-1)*m+j-1,inf); if(j<m) add_edge((i-1)*m+j,(i-1)*m+j+1,inf); else add_edge((i-1)*m+j,t,x); op^=1; ans-=dinic(); printf("%d",ans);
dfs终止条件没写调了半天(笑哭)
以上是关于方格取数(网络流24题)的主要内容,如果未能解决你的问题,请参考以下文章