题目大意:
一堆兔子要从点[1,1]走到点[N,M],给出所有横行路径,纵行路径,对角线路径所能容纳的兔子数K,如果要封锁一条路径,则需要同样的K只狼,问在将兔子一网打尽的前提下,参与的狼的数量要最小,这个最小值是多少。
N,M均小于等于1000.
题解:
这题是一道很显然的最小割问题,
因为最小割等于最大流,
所以我们建边然后跑一波最大流即可
注意建边的数组要开2*3*N*M,不然会炸
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define INF 0xfffffff
#define N 1000005
using namespace std;
queue <int> Q;
struct node{
int to,next,w;
}a[8*N];
int ls[N],d[N],n,m,maxflow=0,cnt=1,S,T;
void add(int u , int v , int w){
cnt++; a[cnt].to = v; a[cnt].next = ls[u]; a[cnt].w = w; ls[u] = cnt;
cnt++; a[cnt].to = u; a[cnt].next = ls[v]; a[cnt].w = w; ls[v] = cnt;
}
bool bfs(){
while (Q.size()) Q.pop();
for (int i = S; i <= T; i++) d[i] = 0;
d[S] = 1;
Q.push(S);
while (Q.size()){
int u = Q.front();
Q.pop();
for (int i = ls[u]; i ; i =a[i].next)
if (a[i].w && !d[a[i].to]){
d[a[i].to] = d[u]+1;
Q.push(a[i].to);
if (a[i].to == T) return 1;
}
}
return 0;
}
int dfs(int dep , int flow){
if (dep == T) return flow;
int rest = flow,rp = 0;
for (int i = ls[dep]; i && rest ; i = a[i].next)
if (d[a[i].to] == d[dep]+1 && a[i].w){
rp = dfs(a[i].to , min(a[i].w , rest));
if (!rp) d[a[i].to] = 0;
a[i].w -= rp;
a[i^1].w += rp;
rest -= rp;
}
return flow - rest;
}
void dinic(){
int flow;
while (bfs()){
while (flow = dfs(S,INF)) maxflow += flow;
}
}
int main()
{
scanf("%d%d",&n,&m);
int cost;
S=1; T=n*m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m-1; j++){
scanf("%d",&cost);
add(m*(i-1)+j , m*(i-1)+j+1 , cost);
}
for (int i = 1; i <= n-1; i++)
for (int j = 1; j <= m; j++){
scanf("%d",&cost);
add(m*(i-1)+j , m*i+j , cost);
}
for (int i = 1; i <= n-1; i++)
for (int j = 1; j <= m-1; j++){
scanf("%d",&cost);
add(m*(i-1)+j , m*i+j+1 , cost);
}
dinic();
printf("%d\n" , maxflow);
return 0;
}