bzoj1001狼抓兔子
Description
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(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只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14
最小割等于最大流
感觉还是比较好写的
dinic算法
误把反向边和反向弧弄混
调了很久。。。。。。
感谢师兄大佬的指导
em......
某位大佬牛逼啊
想到把反向边和反向弧建在一起
瞬间快了1000多ms
强啊
#include<cstdio> #include<iostream> #include<cstring> const int M=3*1000*1000+5,N=1000*1000+100; struct node { int to,next,v; }e[M*4]; int first[N],cnt=1,t; int deep[N],qu[N]; int cur[N]; void insert(int u,int v,int q) { e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;e[cnt].v=q; } int read() { char t=getchar(); int ans=0; while(t<'0'||t>'9') t=getchar (); while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar(); return ans; } bool bfs() { memset(deep,-1,sizeof(deep)); deep[1]=0; int i=1,j=2; qu[1]=1; while(i!=j) { int r=qu[i++];if(i==N) i=1; for(int k=first[r];k;k=e[k].next) if(deep[e[k].to]==-1&&e[k].v) { deep[e[k].to]=deep[r]+1; qu[j++]=e[k].to;if(j==N) j=1; } } if(deep[t]==-1) return 0; return 1; } int dfs(int x,int a) { if(x==t||a==0) return a; int flow=0,t; for(int& k=cur[x];k;k=e[k].next) if(deep[e[k].to]==deep[x]+1&&e[k].v) { t=dfs(e[k].to,std::min(a,e[k].v)); e[k].v-=t;e[k^1].v+=t; flow+=t;a-=t; if(!a) break; } if(!flow) deep[x]=-1; return flow; } int main() { int h=read(),l=read(),q; for(int i=1;i<=h;i++) for(int j=1;j<l;j++) { q=read(); //反向边 insert((i-1)*l+j,(i-1)*l+j+1,q); insert((i-1)*l+j+1,(i-1)*l+j,q); } for(int i=1;i<h;i++) for(int j=1;j<=l;j++) { q=read(); insert((i-1)*l+j,i*l+j,q); insert(i*l+j,(i-1)*l+j,q); } for(int i=1;i<h;i++) for(int j=1;j<l;j++) { q=read(); insert((i-1)*l+j,i*l+j+1,q); insert(i*l+j+1,(i-1)*l+j,q); } t=h*l; int ans=0; while(bfs()) { for(int i=1;i<=t;i++) cur[i]=first[i]; ans+=dfs(1,1e8); } printf("%d\n",ans); return 0; }
spfa 周冬《两极相通——浅析最大—最小定理在信息学竞赛中的应用》
利用最短路求最小割#include<cstdio> const int N=2*1e6+15,M=3*1e6+15; struct node { int to,v,next; }e[M*2]; int cnt=0; int first[N]; int qu[N],book[N],dis[N]; void insert(int u,int v,int q) { e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;e[cnt].v=q; e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt;e[cnt].v=q; // printf("%d %d %d\n",u,v,q); } int read() { int ans=0; char t=getchar(); while(t>'9'||t<'0') t=getchar(); while(t<='9'&&t>='0') ans=ans*10+t-'0',t=getchar(); return ans; } void spfa(int t) { int i=1,j=2; dis[0]=0; for(int i=1;i<=t;i++) dis[i]=1e8; qu[1]=0;book[0]=1; while(i!=j) { int r=qu[i++];book[r]=0;if(i==N) i=0; for(int k=first[r];k;k=e[k].next) { if(dis[e[k].to]>dis[r]+e[k].v) { dis[e[k].to]=dis[r]+e[k].v; // printf("%d to%d ==%d\n",r,e[k].to,dis[e[k].to]); if(!book[e[k].to]) { if(dis[e[k].to]<dis[qu[i]])//slf优化 { i--; if(i<0) i=N-2; qu[i]=e[k].to; } else qu[j++]=e[k].to; if(j==N) j=0; book[e[k].to]=1; } } } } printf("%d\n",dis[t]); } int main() { int h=read(),l=read(),q; int s=0,t=(l-1)*2*(h-1)+1; if(h!=1&&l!=1) { for(int i=1;i<=h;i++) for(int j=1;j<l;j++) { q=read(); if(i==1) insert((i-1)*2*(l-1)+j*2,s,q); else if(i==h) insert(t,(i-2)*2*(l-1)+j*2-1,q); else insert((i-1)*2*(l-1)+j*2,(i-2)*2*(l-1)+j*2-1,q); } for(int i=1;i<h;i++) for(int j=1;j<=l;j++) { q=read(); if(j==1) insert(t,(i-1)*2*(l-1)+(j-1)*2+1,q); else if(j==l) insert(s,(i-1)*2*(l-1)+(j-1)*2,q); else insert((i-1)*2*(l-1)+(j-1)*2+1,(i-1)*2*(l-1)+(j-1)*2,q); } for(int i=1;i<h;i++) for(int j=1;j<l;j++) { q=read(); insert((i-1)*2*(l-1)+(j-1)*2+1,(i-1)*2*(l-1)+(j-1)*2+2,q); } spfa(t); } else { int sum=1e8; for(int i=1;i<=h;i++) for(int j=1;j<l;j++) { q=read(); sum=sum<q?sum:q; } for(int i=1;i<h;i++) for(int j=1;j<=l;j++) { q=read(); sum=sum<q?sum:q; } printf("%d\n",sum); } return 0; }