BZOJ 1001 狼抓兔子 (网络流最小割/平面图的对偶图的最短路)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001

算法讨论:

1、可以用最大流做,最大流等于最小割。

2、可以把这个图转化其对偶图,然后在对偶图上跑最短路即可。

一个平面图的最小割等价于其对偶图从S到T的最短路。并不是所有的图都有对偶图,平面图也有一定的要求,自己可以百度一下。

代码(用BZOJ的数据测过了,但是在BZOJ上过不去。爆WA,并不知道是为什么,里面有个特判,并不知道有没有用处。)

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 #include <cstdio>
  6 
  7 using namespace std;
  8 
  9 const int N = 2000000 + 5;
 10 const int inf = 0x3f3f3f3f;
 11 
 12 int n, cnt, m;
 13 int head[N], que[N], dis[N];
 14 bool vis[N];
 15 
 16 struct Edge {
 17   int from, to, dis, next;
 18 }edges[N * 4];
 19 
 20 void add(int u, int v, int dis) {
 21   ++ cnt;
 22   edges[cnt].from = u; edges[cnt].to = v;
 23   edges[cnt].dis = dis; edges[cnt].next = head[u];
 24   head[u] = cnt;
 25   ++ cnt;
 26   edges[cnt].from = v; edges[cnt].to = u;
 27   edges[cnt].dis = dis; edges[cnt].next = head[v];
 28   head[v] = cnt;
 29 }
 30 
 31 void spfa(int s, int t) {
 32   int h = 1, tail = 1;
 33   for(int i = s; i <= t; ++ i) {
 34     dis[i] = inf;
 35     vis[i] = false;
 36   }
 37   vis[s] = true; dis[s] = 0;
 38   que[h] = s;
 39   while(h <= tail) {
 40     int x = que[h];
 41     vis[x] = false;
 42     for(int i = head[x]; i; i = edges[i].next) {
 43       int v = edges[i].to;
 44       if(dis[v] > dis[x] + edges[i].dis) {
 45         dis[v] = dis[x] + edges[i].dis;
 46         if(!vis[v]) {
 47           que[++ tail] = v;
 48           vis[v] = true;
 49         }
 50       }
 51     }
 52     ++ h;
 53   }
 54   printf("%d\n", dis[t]);
 55 }
 56 
 57 #define stone
 58 
 59 int main() {
 60 #ifndef stone
 61 
 62   freopen("bjrabbit.in", "r", stdin);
 63   freopen("bjrabbit.out", "w", stdout);
 64 
 65 #endif
 66   
 67   int tmp, s, t, x, mn = 0x3f3f3f3f;
 68   scanf("%d%d", &n, &m);
 69   s = 0; t = (n - 1) * (m - 1) * 2 + 1;
 70   tmp = (m - 1) * 2;
 71   for(int i = 1; i <= n; ++ i) {
 72     for(int j = 1; j < m; ++ j) {
 73       scanf("%d", &x);
 74       mn = min(x, mn);
 75       if(i == 1) {
 76         add(j * 2 + tmp * (i - 1), t, x);
 77       }
 78       else if(i == n) {
 79         add(s, j * 2 + tmp * (i - 2) - 1, x);
 80       }
 81       else {
 82         add(j * 2 + tmp * (i - 1), j * 2 + tmp * (i - 2) - 1, x);
 83       }
 84     }
 85   }
 86   for(int i = 1; i < n; ++ i) {
 87     for(int j = 1; j <= m; ++ j) {
 88       scanf("%d", &x);
 89       mn = min(x, mn);
 90       if(j == 1) {
 91         add(s, tmp * (i - 1) + 1, x);
 92       }
 93       else if(j == m) {
 94         add(tmp * i, t, x);
 95       }
 96       else {
 97         add(tmp * (i - 1) + 2 * (j - 1), tmp * (i - 1) + 2 * (j - 1) + 1, x);
 98       }
 99     }
100   }
101   for(int i = 1; i < n; ++ i) {
102     for(int j = 1; j < m; ++ j) {
103       scanf("%d", &x);
104       mn = min(mn, x);
105       add(tmp * (i - 1) + j * 2, tmp * (i - 1) + j * 2 - 1, x);
106     }
107   }
108   if(n == 1 || m == 1) printf("%d\n", mn);
109   else spfa(s, t);
110 
111 #ifndef stone
112 
113   fclose(stdin); fclose(stdout);
114 
115 #endif
116   
117   return 0;
118 }
1001

 

posted @ 2016-03-22 18:55  漫步者。!~  阅读(338)  评论(0编辑  收藏  举报