[BJOI2006] [BZOJ1001] 狼抓兔子|最大流|最短路
2015-05-01 10:37
603 查看
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(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只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦.
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
先让我哭一会……坑了我好久的题。
开始时dinic怎么写都超时,于是看了题解,是一个奇怪的最短路……让我很不解。后来同校的大神用dinic过了……于是乎,我就改了一上午的dinic,终于过掉了。
分析:
建图没什么好说的,直接挨着标号,处理好坐标就好了。然后就是dinic。
很久以来,我写dinic一直是N次dfs找增广路直到找不到。然后就出现了16000+MS完美Time_Limit_Exceed……超时不可能出现在BFS距离标号上,那就只能是增广路的问题了。
做了一点小改动……直接秒了。详见代码。
左上角点为(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个数,表示斜向道路的权值. 输入文件保证不超过10MOutput
输出一个整数,表示参与伏击的狼的最小数量.Sample Input
3 45 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14958965 | ws_fqk | 1001 | Accepted | 83304 kb | 1924 ms | C++/Edit | 2579 B | 2015-05-01 10:20:13 |
958941 | ws_fqk | 1001 | Time_Limit_Exceed | 83304 kb | 16028 ms | C++/Edit | 2552 B | 2015-05-01 10:07:56 |
958919 | ws_fqk | 1001 | Time_Limit_Exceed | 87208 kb | 16032 ms | C++/Edit | 2522 B | 2015-05-01 09:48:54 |
开始时dinic怎么写都超时,于是看了题解,是一个奇怪的最短路……让我很不解。后来同校的大神用dinic过了……于是乎,我就改了一上午的dinic,终于过掉了。
分析:
建图没什么好说的,直接挨着标号,处理好坐标就好了。然后就是dinic。
很久以来,我写dinic一直是N次dfs找增广路直到找不到。然后就出现了16000+MS完美Time_Limit_Exceed……超时不可能出现在BFS距离标号上,那就只能是增广路的问题了。
做了一点小改动……直接秒了。详见代码。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<vector> #include<cmath> using namespace std; int next[6000000],head[1000001],list[6000000],key[6000000],dis[1000001],q[1000001],n,m,top,ans,sum,delta,x; void insert(int x,int y,int z) { top++; next[top]=head[x]; head[x]=top; list[top]=y; key[top]=z; } bool BFS() { memset(dis,0xff,sizeof(dis)); dis[1]=0; int x,y,l=0,r=1; q[1]=1; while (l<r) { l++; y=q[l]; x=head[y]; while (x!=0) { if (dis[list[x]]<0&&key[x]>0) { dis[list[x]]=dis[y]+1; r++; q[r]=list[x]; } x=next[x]; } } if (dis[sum]>0) return true; else return false; } int find(int x,int flow) { if (x==sum) return flow; int a=0,y=head[x],ff=0; while (y!=0) { if (key[y]>0&&dis[list[y]]==dis[x]+1) { a=flow-ff; a=find(list[y],min(key[y],a)); key[y]-=a; key[y^1]+=a; ff+=a; if (ff==flow) return flow; } y=next[y]; } if (!ff) dis[x]=-1; 关键就在这一句啊! return ff; } int main() { scanf("%d%d",&n,&m); top=0; for (int i=1;i<=n;i++) for (int j=1;j<m;j++) { scanf("%d",&x); insert((i-1)*m+j,(i-1)*m+j+1,x); insert((i-1)*m+j+1,(i-1)*m+j,x); } for (int i=1;i<n;i++) for (int j=1;j<=m;j++) { scanf("%d",&x); insert((i-1)*m+j,i*m+j,x); insert(i*m+j,(i-1)*m+j,x); } for (int i=1;i<n;i++) for (int j=1;j<m;j++) { scanf("%d",&x); insert((i-1)*m+j,i*m+j+1,x); insert(i*m+j+1,(i-1)*m+j,x); } ans=0; sum=n*m; while (BFS()) ans+=find(1,0x7fffffff); printf("%d",ans); return 0; }
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<vector> #include<cmath> #include<queue> #include<map> #include<set> #define M 2000001 #define INF 1000000007 using namespace std; int next[4*M],list[4*M],key[4*M]; int dis[M],q[M],head[M]; bool v[M]; int n,m,S,T,x,cnt,t,w; void insert(int x,int y,int z) { next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; key[cnt]=z; } int main() { scanf("%d%d",&n,&m); T=2*(n-1)*(m-1)+1; for (int i=1;i<m;i++) { scanf("%d",&x); insert(i*2,T,x); insert(T,i*2,x); } for (int i=1;i<=n-2;i++) for (int j=1;j<m;j++) { scanf("%d",&x); insert(2*(i-1)*(m-1)+2*j-1,2*i*(m-1)+2*j,x); insert(2*i*(m-1)+2*j,2*(i-1)*(m-1)+2*j-1,x); } for (int i=1;i<m;i++) { scanf("%d",&x); insert(S,2*(n-2)*(m-1)+i*2-1,x); insert(2*(n-2)*(m-1)+i*2-1,S,x); } for (int i=1;i<n;i++) { scanf("%d",&x); insert(S,2*(i-1)*(m-1)+1,x); insert(2*(i-1)*(m-1)+1,S,x); for (int j=1;j<=m-2;j++) { scanf("%d",&x); insert(2*(i-1)*(m-1)+j*2,2*(i-1)*(m-1)+j*2+1,x); insert(2*(i-1)*(m-1)+j*2+1,2*(i-1)*(m-1)+j*2,x); } scanf("%d",&x); insert(2*i*(m-1),T,x); insert(T,2*i*(m-1),x); } for (int i=1;i<n;i++) for (int j=1;j<m;j++) { scanf("%d",&x); insert(2*(i-1)*(m-1)+2*j-1,2*(i-1)*(m-1)+2*j,x); insert(2*(i-1)*(m-1)+2*j,2*(i-1)*(m-1)+2*j-1,x); } for (int i=1;i<=T;i++) dis[i]=INF; memset(v,0,sizeof(v)); v[0]=1; q[1]=0; dis[0]=0; t=0;w=1; while (t<w) { x=q[++t]; for (int i=head[x];i;i=next[i]) if (dis[list[i]]>dis[x]+key[i]) { dis[list[i]]=dis[x]+key[i]; if (!v[list[i]]) { v[list[i]]=1; q[++w]=list[i]; } } v[x]=0; } printf("%d",dis[T]); return 0; }
相关文章推荐
- [bzoj1001][BJOI2006]狼抓兔子——最大流转最短路,平面图
- BZOJ 1001([BeiJing2006]狼抓兔子-最大流转对偶图最短路)
- BZOJ 1001([BeiJing2006]狼抓兔子-最大流转对偶图最短路)
- bzoj1001 [BeiJing2006]狼抓兔子(最小割/平面图最大流转对偶图最短路)
- BZOJ1001 BJOI2006狼抓兔子(最小割+最短路)
- 【平面图转对偶图】【最短路】【Beijing 2006】【bzoj 1001】狼抓兔子
- BZOJ 1001: [BeiJing2006]狼抓兔子(最短路)
- 【BJOI2006】bzoj1001 狼抓兔子
- bzoj1001 [BeiJing2006]狼抓兔子(网络流dinic算法||最短路spfa)
- BZOJ 1001 [BeiJing2006] 狼抓兔子(平面图最大流)
- BZOJ1001 [BeiJing2006]狼抓兔子(平面图最小割转最短路)
- [平面图转最短路]BZOJ1001:[BeiJing2006]狼抓兔子
- 【BZOJ1001】[BeiJing2006]狼抓兔子【最小割】【最短路】【对偶图】
- [BJOI2006][bzoj1001] 狼抓兔子 [最小割]
- [BZOJ1001] [BJOI2006] 狼抓兔子
- 【bzoj1001】【最短路】【对偶图】【最大流转最小割】狼抓兔子题解
- BZOJ 1001 狼抓兔子 平面图上的最大流--跑最短路
- bzoj1001: [BeiJing2006]狼抓兔子(最大流)
- 【BZOJ1001】【Beijing2006】狼抓兔子(平面图转对偶图:最小割+最短路)
- 【BZOJ】 1001 [BeiJing2006]狼抓兔子 网络最大流