[BJOI2006][bzoj1001] 狼抓兔子 [最小割]
题面:
思路:
其实就是一道最小割的题目......
我的写法加了两个优化,常数比较小,所以过掉了
一个是当前弧,一个是若当前点并不能流出去,那么标记dep为-1
听说正解是对偶图最短路?可以找时间学一学......
Code:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define inf 1e9 #define id(i,j) (i-1)*m+j using namespace std; inline int read(){ int re=0,flag=1;char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') flag=-1; ch=getchar(); } while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar(); return re*flag; } int n,m,cnt=-1,ans,first[1000010],dep[1000010],cur[1000010]; int q[1000010],head,tail; struct edge{ int to,next,cap; }a[6000010]; inline void add(int u,int v,int cap){ a[++cnt]=(edge){v,first[u],cap};first[u]=cnt; a[++cnt]=(edge){u,first[v],cap};first[v]=cnt; } bool bfs(int s,int t){ int i,u,v; head=0,tail=1;q[0]=s; for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i]; dep[s]=1; while(head<tail){ u=q[head++]; for(i=first[u];~i;i=a[i].next){ v=a[i].to; if(~dep[v]||(!a[i].cap)) continue; dep[v]=dep[u]+1; q[tail++]=v; } } return ~dep[t]; } int dfs(int u,int t,int limit){ if(u==t||!limit) return limit; int i,v,f,flow=0; for(i=cur[u];~i;i=a[i].next){ v=a[i].to;cur[u]=i;//优化一 if(dep[v]==dep[u]+1&&a[i].cap>0){ f=dfs(v,t,min(limit,a[i].cap)); if(f){ flow+=f;limit-=f; a[i].cap-=f;a[i^1].cap+=f; if(!limit) return flow; } else{ dep[v]=-1;continue;//优化二 } } } return flow; } void dinic(int s,int t){ int tmp; while(bfs(s,t)){ while(tmp=dfs(s,t,inf)) ans+=tmp; } } int main(){ memset(first,-1,sizeof(first)); int i,j,t1; n=read();m=read(); for(i=1;i<=n;i++){ for(j=1;j<m;j++){ t1=read(); add(id(i,j),id(i,j+1),t1); } } for(i=1;i<n;i++){ for(j=1;j<=m;j++){ t1=read(); add(id(i,j),id(i+1,j),t1); } } for(i=1;i<n;i++){ for(j=1;j<m;j++){ t1=read(); add(id(i,j),id(i+1,j+1),t1); } } dinic(1,n*m); printf("%d",ans); }