题意不难理解,要求最少数量,其实就是求一个最小割。建图也简单。。
有几个坑点:
①边的数量大约是6倍的nm (因为三个方向)
②点的数量只有nm,最多1e6,注意别开大了MLE
其他就是正常的最小割模板。
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int maxn = 6000005; //n*(m-1)+(n-1)*m+(n-1)*(m-2)+....
const int inf = 0x3f3f3f3f;
int head[maxn],tot;
struct node{
int to,nxt,cap,flow;
}E[maxn];
int n,m,w[1005][1005],st,ed;
void init(){
memset(head,-1,sizeof(head[0])*(n*m+10));
tot = 0;
}
void addedge(int u,int v,int w,int rw = 0){
E[tot].to = v;
E[tot].nxt = head[u];
//E[tot].cap = w;
E[tot].flow = w;
head[u] = tot++;
E[tot].to = u;
E[tot].nxt = head[v];
//E[tot].cap = rw;
E[tot].flow = w;
head[v] = tot++;
}
int getid(int i,int j){
return (i-1)*m+j;
}
int dep[maxn>>2],cur[maxn>>2],q[maxn>>2];
bool bfs(int s,int t){
memset(dep,-1,sizeof(dep[0])*(t+1));
int h=1,ti=0;
dep[1]=0;
q[1]=1;
while (ti!=h)
{
int u=q[++ti];
for (int i=head[u]; i!=-1; i=E[i].nxt)
{
int v=E[i].to;
if ((dep[v]==-1)&&(E[i].flow>0))
{
dep[v]=dep[u]+1;
q[++h]=v;
}
}
}
if (dep[t]==-1)
return 0;
return 1;
}
int dfs(int u,int flow,int s,int t)
{
if (u==t)
return flow;
int used = 0;
for (int i=head[u]; i!=-1; i=E[i].nxt)
{
int v=E[i].to;
if ((dep[v]==dep[u]+1)&&(E[i].flow>0))
{
int di=dfs(v,min(flow-used,E[i].flow),s,t);
if (di>0)
{
E[i].flow-=di;
E[i^1].flow+=di;
used += di;
if(used == flow)
return flow;
}
}
}
if(!used) dep[u] = -1;
return used;
}
int dinic(int s,int t, int n)
{
int ans=0;//求解最大流
while (bfs(1,n))
{
for (int i=0; i<=n; i++)
cur[i]=head[i];
while (int di=dfs(1,inf,1,n))
ans+=di;
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
init();
st = 1, ed = n*m;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m-1; j++){
scanf("%d",&w[i][j]);
}
for(int j = 2; j <= m; j++){
addedge(getid(i,j-1),getid(i,j),w[i][j-1]);
}
}
for(int i = 1; i <= n-1; i++){
for(int j = 1; j <= m; j++){
scanf("%d",&w[i][j]);
}
for(int j = 1; j <= m; j++){
addedge(getid(i,j),getid(i+1,j),w[i][j]);
}
}
for(int i = 1; i <= n-1; i++){
for(int j = 1; j <= m-1; j++){
scanf("%d",&w[i][j]);
}
for(int j = 1; j <= m-1; j++){
addedge(getid(i,j),getid(i+1,j+1),w[i][j]);
}
}
printf("%d\n",dinic(st,ed,ed));
}