码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ1001] [Beijing2006] 狼抓兔子 (最短路)

时间:2016-04-03 23:56:43      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:

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

Sample Output

14

HINT 

   2015.4.16新加数据一组,可能会卡掉从前可以过的程序。

Solution

  乍一看是一道网络流的题,但是实际写完会发现超时超到姥姥家去了。
  定理:平面图的最大流=该图对偶图的最短路,某形象解释见某贴心神犇
  之后SPFA乱搞获Dijkstra乱搞,不过我建边的方式有点鬼畜。
 
技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 using namespace std;
  4 struct node
  5 {
  6     int v, w;
  7 }edge[6000005];
  8 int fst[2000005], nxt[6000005], sss, ttt, dis[2000005], q[2000005], front, back;
  9 bool inq[2000005];
 10  
 11 void qscanf(int &x)
 12 {
 13     char c = getchar();
 14     x = 0;
 15     while(c < 0 || c > 9)
 16         c = getchar();
 17     while(c >= 0 && c <= 9)
 18         x = x * 10 + c - 0, c = getchar();
 19 }
 20  
 21 void addedge(int i, int u, int v, int w)
 22 {
 23     edge[i << 1] = (node){v, w}, nxt[i << 1] = fst[u], fst[u] = i << 1;
 24     edge[i << 1 | 1] = (node){u, w}, nxt[i << 1 | 1] = fst[v], fst[v] = i << 1 | 1;
 25 }
 26  
 27 void SPFA()
 28 {
 29     memset(dis, 63, sizeof(dis));
 30     dis[sss] = 0, inq[sss] = q[++back] = sss;
 31     while(front != back)
 32     {
 33         int u = q[++front % 2000000];
 34         inq[u] = false, front %= 2000000;
 35         for(int i = fst[u]; i; i = nxt[i])
 36         {
 37             int v = edge[i].v, w = edge[i].w;
 38             if(dis[v] > dis[u] + w)
 39             {
 40                 dis[v] = dis[u] + w;
 41                 if(!inq[v])
 42                 {
 43                     dis[v] = dis[u] + w;
 44                     inq[v] = true;
 45                     q[++back % 2000000] = v;
 46                     back %= 2000000;
 47                 }
 48             }
 49         }
 50     }
 51 }
 52  
 53 int main()
 54 {
 55     int n, m, etot = 0;
 56     qscanf(n), qscanf(m);
 57     n--, m--;
 58     if(n && m)
 59     {
 60         sss = n * m * 2 + 1, ttt = n * m * 2 + 2;
 61         for(int i = 1; i <= n + 1; i++)
 62             for(int j = 1; j <= m; j++)
 63             {
 64                 int u = ((i - 2) * m + j) * 2 - 1, v = ((i - 1) * m + j) * 2, w;
 65                 qscanf(w);
 66                 if(i == 1)
 67                     addedge(++etot, sss, v, w);
 68                 else if(i == n + 1)
 69                     addedge(++etot, u, ttt, w);
 70                 else
 71                     addedge(++etot, u, v, w);
 72             }
 73         for(int i = 1; i <= n; i++)
 74             for(int j = 1; j <= m + 1; j++)
 75             {
 76                 int u = ((i - 1) * m + j) * 2 - 2, v = ((i - 1) * m + j) * 2 - 1, w;
 77                 qscanf(w);
 78                 if(j == 1)
 79                     addedge(++etot, ttt, v, w);
 80                 else if(j == m + 1)
 81                     addedge(++etot, u, sss, w);
 82                 else
 83                     addedge(++etot, u, v, w);
 84             }
 85         for(int i = 1; i <= n; i++)
 86             for(int j = 1; j <= m; j++)
 87             {
 88                 int u = ((i - 1) * m + j) * 2 - 1, v = ((i - 1) * m + j) * 2, w;
 89                 qscanf(w), addedge(++etot, u, v, w);
 90             }
 91         SPFA();
 92     }
 93     else
 94     {
 95         if(m)
 96             n = m;
 97         dis[ttt] = 2147483647;
 98         for(int i = 1; i <= n; i++)
 99         {
100             qscanf(fst[i]);
101             if(dis[ttt] > fst[i])
102                 dis[ttt] = fst[i];
103         }
104     }
105     printf("%d\n", dis[ttt]);
106     return 0;
107 }
View Code

 

 

[BZOJ1001] [Beijing2006] 狼抓兔子 (最短路)

标签:

原文地址:http://www.cnblogs.com/CtrlCV/p/5350850.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!