zoukankan      html  css  js  c++  java
  • BZOJ 1001 狼抓兔子 (最小割转化成最短路)

    1001: [BeiJing2006]狼抓兔子

    Time Limit: 15 Sec  Memory Limit: 162 MB
    Submit: 27715  Solved: 7134
    [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

    析:很容易看出是裸板的最小割,然后可能会超时,边实在是太多了,有一种特殊的方法,可以把平面图转成最短路来求,也就是利用对偶图,把原图的而看成新图的点,原图的边与两个面相连的,加一条边,然后再多加一个起点和终点。跑一次最短路即可。

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #include <list>
    #include <assert.h>
    #include <bitset>
    #define debug() puts("++++");
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define pb push_back
    #define sqr(x) ((x)*(x))
    #define ms(a,b) memset(a, b, sizeof a)
    #define sz size()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    //#define all 1,n,1
    #define FOR(i,x,n)  for(int i = (x); i < (n); ++i)
    #define freopenr freopen("in.txt", "r", stdin)
    #define freopenw freopen("out.txt", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const double inf = 1e20;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 2e6 + 10;
    const int maxm = 100 + 10;
    const ULL mod = 10007;
    const int dr[] = {-1, 0, 1, 0};
    const int dc[] = {0, -1, 0, 1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline bool is_in(int r, int c) {
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    struct Edge{
      int to, dist, next;
    };
    
    struct HeapNode{
      int d, u;
      bool operator < (const HeapNode &p) const{
        return d > p.d;
      }
    };
    Edge edge[maxn*3];
    int head[maxn], cnt;
    int d[maxn];
    bool done[maxn];
    
    inline void addEdge(int u, int v, int dist){
      edge[cnt].to = v;
      edge[cnt].dist = dist;
      edge[cnt].next = head[u];
      head[u] = cnt++;
    }
    
    void dijkstra(int s){
      priority_queue<HeapNode> pq;
      ms(d, INF);  d[s] = 0;
      ms(done, 0);
      pq.push((HeapNode){0, s});
      while(!pq.empty()){
        HeapNode x = pq.top();  pq.pop();
        int u = x.u;
        if(done[u])  continue;
        done[u] = 1;
        for(int i = head[u]; ~i; i = edge[i].next){
          int v = edge[i].to, dist = edge[i].dist;
          if(d[v] > d[u] + dist){
            d[v] = d[u] + dist;
            pq.push((HeapNode){d[v], v});
          }
        }
      }
    }
    
    
    int main(){
      scanf("%d %d", &n, &m);
      if(n == 1 || m == 1){
        n = max(n, m);
        int ans = INF;
        for(int i = 0; i < n; ++i){
          int x;
          scanf("%d", &x);
          ans = min(ans, x);
        }
        printf("%d
    ", ans);
        return 0;
      }
      ms(head, -1);  cnt = 0;
      int s = 0, t = 2 * n * m + 1;
      FOR(i, 0, n)  for(int j = 1; j < (m-1<<1); j += 2){
        int dist;
        scanf("%d", &dist);
        int from = i == 0 ? s : (i-1)*(m-1<<1)+j+1;
        int to = i + 1 == n ? t : i*(m-1<<1)+j;
        addEdge(from, to, dist);
        addEdge(to, from, dist);
      }
      FOR(i, 0, n-1)  for(int j = 1; j <= m; ++j){
        int dist;
        scanf("%d", &dist);
        int from = j == 1 ? t : i*(m-1<<1)+(j<<1)-3;
        int to = j == m ? s : i*(m-1<<1)+(j<<1);
        addEdge(from, to, dist);
        addEdge(to, from, dist);
      }
      FOR(i, 0, n-1)  for(int j = 1; j < m; ++j){
        int dist;
        scanf("%d", &dist);
        int from = i*(m-1<<1)+(j<<1);
        int to = from - 1;
        addEdge(from, to, dist);
        addEdge(to, from, dist);
      }
      dijkstra(s);
      printf("%d
    ", d[t]);
      return 0;
    }
    

      

  • 相关阅读:
    【miscellaneous】北斗短报文
    【miscellaneous】GPRS本质论
    【miscellaneous】GPRS本质论
    【视频处理】模拟视频与数字视频的区别
    【视频处理】模拟视频与数字视频的区别
    【视频处理】模拟视频信号及其传输
    【视频处理】模拟视频信号及其传输
    【机器学习】贝叶斯决策论小结
    【机器学习】贝叶斯决策论小结
    【VS开发】DLL和ocx的区别
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/7622961.html
Copyright © 2011-2022 走看看