题目描述 传送门
现在小朋友们最喜欢的”喜羊羊与灰太狼”,话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路
1:(x,y)<==>(x+1,y)
2:(x,y)<==>(x,y+1)
3:(x,y)<==>(x+1,y+1)
道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
平面网格图求最小割转化为求最短路。
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define FOR(I,A) for(int I=0;I<A;I++)
using namespace std;
const int maxm=6000000;
struct Edge{
int to,dist,nxt;
Edge(int t=0,int d=0,int n=0):to(t),dist(d),nxt(n){}
}E[maxm];
int d[2000000],v[2000000],cnt=1,h[2000000];
void addedge(int f,int t,int d){
E[cnt]=Edge(t,d,h[f]);
h[f]=cnt++;
E[cnt]=Edge(f,d,h[t]);
h[t]=cnt++;
}
int main(){
memset(h,0,sizeof(h));
int n,m;
cin>>n>>m;
int nm=(n-1)*(m-1)*2;
int x,a,b;
FOR(i,n) FOR(j,m-1){
scanf("%d",&x);
a=i*(m-1)*2+j*2+2;
b=a-(m-1)*2-1;
if(i==n-1) a=0;
if(i==0) b=nm+1;
addedge(a,b,x);
}
FOR(i,n-1) FOR(j,m){
scanf("%d",&x);
a=i*(m-1)*2+j*2+1;
b=a-1;
if(j==0) b=0;
if(j==m-1) a=nm+1;
addedge(a,b,x);
}
FOR(i,n-1) FOR(j,m-1){
scanf("%d",&x);
a=i*(m-1)*2+j*2+1;
b=a+1;
addedge(a,b,x);
}
FOR(i,nm+2) d[i]=1e9;
queue<int> q; //SPFA
q.push(0);
d[0]=0;
memset(v,0,sizeof(v));
while(!q.empty()){
int u=q.front();q.pop();v[u]=0;
for(int i=h[u];i;i=E[i].nxt){
Edge& e=E[i];
if(e.dist+d[u]<d[e.to]){
d[e.to]=e.dist+d[u];
if(!v[e.to]){
q.push(e.to);
v[e.to]=1;
}
}
}
}
cout<<d[nm+1]<<endl;
return 0;
}