BZOJ1001: [BeiJing2006]狼抓兔子

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 25579  Solved: 6490
[Submit][Status][Discuss]

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新加数据一组,可能会卡掉从前可以过的程序。

Source

 

【题解】

听说dinic能过的,看到“ 2015.4.16新加数据一组,可能会卡掉从前可以过的程序。”立马删掉写好的dinic

平面图最小割 = 对偶图最短路

https://wenku.baidu.com/view/5a7df375a417866fb84a8e54.html

挺不错的

注意细节。。。

n = 1/m = 1的时候,会有一个边界的边没有建上去

需要特判

或者改一下读入时的if else,改成if也行 大概

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <vector>
  8 #define min(a, b) ((a) < (b) ? (a) : (b))
  9 #define max(a, b) ((a) > (b) ? (a) : (b))
 10 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
 11 inline void swap(int &a, int &b)
 12 {
 13     int tmp = a;a = b;b = tmp;
 14 }
 15 inline void read(int &x)
 16 {
 17     x = 0;char ch = getchar(), c = ch;
 18     while(ch < '0' || ch > '9') c = ch, ch = getchar();
 19     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
 20     if(c == '-') x = -x;
 21 }
 22 
 23 const int INF = 0x3f3f3f3f;
 24 const int MAXN = 2100000;
 25 const int MAXM = 7100000;
 26 
 27 struct Edge
 28 {
 29     int v,w,nxt;
 30     Edge(int _v, int _w, int _nxt){v = _v;w = _w;nxt = _nxt;}
 31     Edge(){}
 32 }edge[MAXM];
 33 int head[MAXN + 100], cnt = 1, S = MAXN + 1, T = MAXN + 2;
 34 
 35 inline void insert(int a, int b, int c)
 36 {
 37     edge[++cnt] = Edge(b,c,head[a]);
 38     head[a] = cnt;
 39     edge[++cnt] = Edge(a,c,head[b]);
 40     head[b] = cnt;
 41 }
 42 int n,m;
 43 
 44 int d[MAXN + 100], b[MAXN + 100];
 45 
 46 struct Node
 47 {
 48     int u,w;
 49     Node(int _u, int _w){u = _u;w = _w;}
 50     Node(){}
 51 };
 52 
 53 struct cmp
 54 {
 55     bool operator()(Node a, Node b)
 56     {
 57         return a.w > b.w;
 58     }
 59 };
 60 
 61 std::priority_queue<Node, std::vector<Node>, cmp> q;
 62 
 63 void dij()
 64 {
 65     memset(d, 0x3f, sizeof(d));
 66     d[S] = 0;
 67     q.push(Node(S, 0));
 68     while(q.size())
 69     {
 70         Node now = q.top();q.pop();
 71         if(b[now.u]) continue;
 72         b[now.u] = 1;
 73         for(int pos = head[now.u];pos != -1;pos = edge[pos].nxt)
 74         {
 75             int v = edge[pos].v;
 76             if(d[v] > d[now.u] + edge[pos].w)
 77             {
 78                 d[v] = d[now.u] + edge[pos].w;
 79                 q.push(Node(v, d[v]));
 80             }
 81         }
 82     }
 83 }
 84 
 85 int main()
 86 {
 87     memset(head, -1, sizeof(head));
 88     read(n), read(m);
 89     if(n == 1)
 90     {
 91         int ans = INF;
 92         for(register int i = 1;i < m;++ i)
 93         {
 94             int tmp;read(tmp);
 95             ans = min(ans, tmp);
 96         }
 97         printf("%d", ans);
 98         return 0;
 99     }
100     else if(m == 1)
101     {
102         int ans = INF;
103         for(register int i = 1;i < n;++ i)
104         {
105             int tmp;read(tmp);
106             ans = min(ans, tmp);
107         }
108         printf("%d", ans);
109         return 0;
110     }
111     for(register int i = 0;i < n;++ i)
112         for(register int j = 0;j < m - 1;++ j)
113         {
114             int tmp;read(tmp);
115             if(i == 0) insert(S, (i * m + j) << 1, tmp);
116             else if(i == n - 1) insert(T, ((i - 1) * m + j) << 1 | 1, tmp);
117             else insert((i * m + j) << 1, ((i - 1) * m + j) << 1 | 1, tmp);
118         }
119     for(register int i = 0;i < n - 1;++ i)
120         for(register int j = 0;j < m;++ j)
121         {
122             int tmp;read(tmp);
123             if(j == 0) insert(T, (i * m + j) << 1 | 1, tmp);
124             else if(j == m - 1) insert(S, (i * m + j - 1) << 1, tmp);
125             else insert((i * m + j) << 1 | 1, (i * m + j - 1) << 1 ,tmp);
126         }
127     for(register int i = 0;i < n - 1;++ i)
128         for(register int j = 0;j < m - 1;++ j)
129         {
130             int tmp;read(tmp);
131             insert((i * m + j) << 1, (i * m + j) << 1 | 1, tmp);
132         }
133     dij();
134     printf("%d", d[T]);
135     return 0;
136 } 
BZOJ1001

 

posted @ 2017-12-08 00:15  嘒彼小星  阅读(199)  评论(0编辑  收藏  举报