刷题向》图论》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

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 } 
View Code

 

 
posted @ 2016-09-15 11:25  PencilWang  阅读(451)  评论(0编辑  收藏  举报