网络流24题方格取数问题
Posted wfj_2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流24题方格取数问题相关的知识,希望对你有一定的参考价值。
Description
在一个有m * n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
Input
第1 行有2 个正整数m和n,分别表示棋盘的行数和列数。
接下来的m行,每行有n个正整数,表示棋盘方格中的数。
Output
将取数的最大总和输出
Sample Input
3 3
1 2 3
3 2 3
2 3 1
Sample Output
11
Hint
数据范围:
1<=N,M<=30
正解:二分图最大独立集。
一个二分图的最大独立集等于点权和-最大匹配。
然后这题点权不为1,所以不能用匈牙利算法,只能用最大流。
//It is made by wfj_2048~ #include <algorithm> #include <iostream> #include <complex> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf (1<<30) #define il inline #define RG register #define ll long long #define c(i,j) ( (i-1)*m+j ) #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; struct edge{ int nt,to,flow,cap; }g[200010]; int head[20010],vis[20010],d[20010],q[20010],G[110][110],a[110][110],n,m,S,T,tot,num=1; il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); if (ch==‘-‘) q=-1,ch=getchar(); while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); return q*x; } il void insert(RG int from,RG int to,RG int cap){ g[++num]=(edge){head[from],to,0,cap},head[from]=num; return; } il int bfs(RG int S,RG int T){ memset(vis,0,sizeof(vis)); RG int h=0,t=1; q[t]=S,d[S]=0,vis[S]=1; while (h<t){ RG int x=q[++h],v; for (RG int i=head[x];i;i=g[i].nt){ v=g[i].to; if (!vis[v] && g[i].cap>g[i].flow) vis[v]=1,q[++t]=v,d[v]=d[x]+1; } } return vis[T]; } il int dfs(RG int x,RG int T,RG int a){ if (x==T || a==0) return a; RG int flow=0,f,v; for (RG int i=head[x];i;i=g[i].nt){ v=g[i].to; if (d[v]==d[x]+1 && g[i].cap>g[i].flow){ f=dfs(v,T,min(a,g[i].cap-g[i].flow)); if (!f){ d[v]=-1; continue; } g[i].flow+=f,g[i^1].flow-=f; flow+=f,a-=f; if (a==0) return flow; } } return flow; } il int maxflow(RG int S,RG int T){ RG int flow=0; while (bfs(S,T)) flow+=dfs(S,T,inf); return flow; } il void work(){ n=gi(),m=gi(); S=n*m+1,T=n*m+2; for (RG int i=1;i<=n;++i) for (RG int j=1;j<=m;++j){ G[i][j]=gi(),tot+=G[i][j]; if (a[i-1][j] || a[i][j-1]){ insert(S,c(i,j),G[i][j]),insert(c(i,j),S,0); if (i-1>0) insert(c(i,j),c(i-1,j),inf),insert(c(i-1,j),c(i,j),0); if (j-1>0) insert(c(i,j),c(i,j-1),inf),insert(c(i,j-1),c(i,j),0); if (i+1<=n) insert(c(i,j),c(i+1,j),inf),insert(c(i+1,j),c(i,j),0); if (j+1<=m) insert(c(i,j),c(i,j+1),inf),insert(c(i,j+1),c(i,j),0); } else a[i][j]=1,insert(c(i,j),T,G[i][j]),insert(T,c(i,j),0); } printf("%d\n",tot-maxflow(S,T)); return; } int main(){ File("number"); work(); return 0; }
以上是关于网络流24题方格取数问题的主要内容,如果未能解决你的问题,请参考以下文章