刷题向》图论》BZOJ1001 平面图最大流、平面图最小割、单源最短路(easy+)
坦白的说这是一道水题,但是因为是BZOJ上的1001,所以这道题有着特殊的意义。
关于最大流转最短路的博客链接如下:关于最大流转最短路两三事
这道题的图形很规矩,所以建边和建点还是很简单的。
题目如下
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(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
只要会最大流转最短路就可以轻易A这道题
下面贴出代码
1 #include<stdio.h> 2 struct shit{int aim,next,lon;}e[6000000+20]; 3 int d[2000000+20],a,b,n,m,num,star,ass,quq[2000000+20],point,head[2000000+20]; 4 bool f[2000000+20]; 5 void fuck(int x,int y,int s) 6 { 7 e[++point].aim=x; 8 e[point].lon=s; 9 e[point].next=head[y]; 10 head[y]=point; 11 e[++point].aim=y; 12 e[point].lon=s; 13 e[point].next=head[x]; 14 head[x]=point; 15 } 16 int main() 17 { 18 scanf("%d%d",&n,&m); 19 if (n == 1 || m == 1)//诡异的特判 20 { 21 if (n > m){n=n+m;m=n-m;n=n-m;} 22 int ans = 214748364; 23 for (int i = 1; i < m; ++i) 24 { 25 int x; 26 scanf("%d",&x); 27 if (x < ans) ans = x; 28 } 29 printf("%d\n", ans); 30 return 0; 31 } 32 int S=0,T=(n-1)*(m-1)*2+1;//建图 33 for(int i=0;i<n;i++) 34 for(int j=1;j<m;j++) 35 { 36 scanf("%d",&num); 37 a=(i*2-1)*(m-1)+j; 38 b=i*2*(m-1)+j; 39 if(i==0)a=S; 40 if(i==n-1)b=T;//以下是存双向边的过程 41 fuck(a,b,num); 42 } 43 for(int i=0;i<n-1;i++) 44 for(int j=1;j<=m;j++) 45 { 46 scanf("%d",&num); 47 a=2*i*(m-1)+j-1; 48 b=(2*i+1)*(m-1)+j; 49 if(j==1)a=T; 50 if(j==m)b=S; 51 fuck(a,b,num); 52 } 53 for(int i=0;i<n-1;i++) 54 for(int j=1;j<m;j++) 55 { 56 scanf("%d",&num); 57 a=2*i*(m-1)+j; 58 b=(2*i+1)*(m-1)+j; 59 fuck(a,b,num); 60 } 61 star=1;//SPFA 62 ass=1; 63 f[S]=true; 64 for(int i=1;i<=T;i++)d[i]=214748364; 65 d[S]=0; 66 while (star<=ass) 67 { 68 int x=quq[star]; 69 f[quq[star++]]=false; 70 for (int i=head[x];i!=0;i=e[i].next) 71 { 72 int y=e[i].aim; 73 if (d[y]>d[x]+e[i].lon) 74 { 75 d[y]=d[x]+e[i].lon; 76 if (f[y]==false) 77 { 78 quq[++ass]=y; 79 f[y]=true; 80 } 81 } 82 } 83 } 84 printf("%d",d[T]); 85 return 0; 86 }