狼抓兔子 BZOJ- 1001 最小割
https://www.lydsy.com/JudgeOnline/problem.php?id=1001
一个图,问你花费多少才能把到终点的所有边堵住...
就是求一个最小割,把$(1,1)$和$(n,m)$ 分开,按他所说的建图就行
不过点数和边数需要开到1e6和1e7...
速度..还能接受,不过这个题应该还能转化为反向图上的最短路解决吧?
(以下是AC代码,但是实际上我本机会RE,不知道为什么..)
#include <bits/stdc++.h> #define ll long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define pp pair<int,int> #define rep(ii,a,b) for(int ii=a;ii<=b;ii++) #define per(ii,a,b) for(int ii=a;ii>=b;ii--) #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(a,b) cout<<#a<<'['<<b<<"]="<<b[a]<<endl using namespace std; const int maxn=1e6+10; const int maxm=1e7+10; const int INF=0x3f3f3f3f; int casn,n,m,k; struct node {int to;int cap;int next;}e[maxm]; int ss,tt,head[maxn],nume,dis[maxn]; inline void addx(int a,int b,int c){ e[++nume]=(node){b,c,head[a]}; head[a]=nume; } inline void add(int a,int b,int c){ addx(a,b,c);addx(b,a,c); } bool bfs(int s=ss,int t=tt){ int top=0,end=1; int q[maxn]; q[0]=s; // for(int i=0;i<=t;i++) dis[i]=0; memset(dis,0,sizeof dis); dis[s]=1; while(top!=end){ int now=q[top++];top%=maxn; for(int i=head[now];i;i=e[i].next){ int to=e[i].to; if(!dis[to]&&e[i].cap){ dis[to]=dis[now]+1; if(to==t)break; q[end++]=to;end%=maxn; } } } return dis[t]; } int dfs(int now=ss,int last=INF){ if(now==tt)return last; int flow=0,det; for(int i=head[now];i;i=e[i].next){ int to=e[i].to; if(e[i].cap&&dis[to]==dis[now]+1){ det=dfs(to,min(last-flow,e[i].cap)); flow+=det; e[i].cap-=det; e[i^1].cap+=det; if(flow==last) return last; } } dis[now]=-1; return flow; } inline int read(){ int num=0,flag=1,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();} while(ch>='0'&&ch<='9'){num=(num<<3)+(num<<1)+ch-'0',ch=getchar();} return flag*num; } int a,b,c; int main(){ //#define test #ifdef test freopen("in.txt","r",stdin);freopen("out.txt","w",stdout); #endif nume=1; n=read();m=read(); rep(i,1,n){ rep(j,2,m){ a=read(); add(m*(i-1)+j,m*(i-1)+j-1,a); } } rep(i,2,n){ rep(j,1,m){ a=read(); add(m*(i-1)+j,m*(i-2)+j,a); } } rep(i,2,n){ rep(j,2,m){ a=read(); add(m*(i-1)+j,m*(i-2)+j-1,a); } } ss=1,tt=n*m; int ans=0; while(bfs()) ans+=dfs(); printf("%d\n",ans); #ifdef test fclose(stdin);fclose(stdout);system("out.txt"); #endif return 0; }