zoukankan      html  css  js  c++  java
  • [BJOI2006]狼抓兔子

    Description

    求一个网格图的最小割。

    Solution

    这个题一看就知道是一个最小割模型,于是就快乐的打了Dinic,也就快乐的TLE了。

    查了查资料才知道,这个题要用到对偶图的知识:平面图最小割对应对偶图最短路。所谓对偶图,就是以原图中的面作为点(将s,t连接以将无界区域分成两部分),原图中的边在对偶图中变为连接相邻的面,于是,显然对偶图中s到t的一条路径代表了原图的一个割,最短路径即最小割。

    Code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
     
    const int N = 2000000 + 10;
    const int M = 6000000 + 10;
     
    int hd[N], nxt[M], to[M], w[M], cnt;
    int n, m, s, t;
    int dis[N], vis[N];
     
    struct node {
        int pos, w;
        node (int a = 0, int b = 0) : pos(a), w(b) {}
        bool operator < (const node &x) const {
            return w > x.w;
        }
    };
     
    inline void Adde(int x, int y, int z) {
        cnt++;
        to[cnt] = y;
        w[cnt] = z;
        nxt[cnt] = hd[x];
        hd[x] = cnt;
    } 
     
    inline void adde(int x, int y, int z) {
        Adde(x, y, z);
        Adde(y, x, z);
    }
     
    void dij() {
        std::priority_queue<node> q;
        memset(dis, 0x3f, sizeof dis);
        dis[s] = 0;
        q.push(node(s, 0));
        node tmp;
        while (!q.empty()) {
            tmp = q.top(); q.pop();
            if (vis[tmp.pos]) continue;
            vis[tmp.pos] = 1;
            for (int i = hd[tmp.pos]; i; i = nxt[i]) {
                if (dis[to[i]] > tmp.w + w[i]) {
                    dis[to[i]] = tmp.w + w[i];
                    q.push(node(to[i], dis[to[i]]));
                }
            }
        }
    }
     
    int main () {
        scanf("%d%d", &n, &m);
        s = 0; t = 2*(n-1)*(m-1)+1;
        int w;
        if (n == 1 || m == 1) {
            if (n > m) std::swap(n, m);
            int ans = 0x3f3f3f3f;
            for (int i = 1; i < m; ++i) scanf("%d", &w), ans = std::min(ans, w);
            printf("%d
    ", ans);
            return 0;
        }
        for (int i = 1; i < m; ++i) {
            scanf("%d", &w);
            adde(i*2, t, w);
        }
        for (int i = 1; i < n-1; ++i) {
            for (int j = 1; j < m; ++j) {
                scanf("%d", &w);
                adde(2*(m-1)*(i-1)+j*2-1, 2*(m-1)*i+j*2, w);
            }
        }
        for (int i = 1; i < m; ++i) {
            scanf("%d", &w);
            adde(s, 2*(m-1)*(n-2)+i*2-1, w);
        }
        for (int i = 1; i < n; ++i) {
            scanf("%d", &w);
            adde(s, 2*(m-1)*(i-1)+1, w);
            for (int j = 2; j < m; ++j) {
                scanf("%d", &w);
                adde(2*(m-1)*(i-1)+j*2-1, 2*(m-1)*(i-1)+j*2-2, w);
            }
            scanf("%d", &w);
            adde(t, 2*(m-1)*i, w);
        }
        for (int i = 1; i < n; ++i) {
            for (int j = 1; j < m; ++j) {
                scanf("%d", &w);
                adde(2*(m-1)*(i-1)+j*2, 2*(m-1)*(i-1)+j*2-1, w);
            }
        }
        dij();
        printf("%d
    ", dis[t]);
        return 0;
    }
  • 相关阅读:
    【SAS NOTE】OUTPUT
    【SAS NOTES】_NULL_
    【SAS NOTE】sas 9.2 安装
    【SAS NOTE】FREQ
    纯数学教程 Page 203 例XLI (1)
    纯数学教程 Page 203 例XLI (3)
    纯数学教程 Page 203 例XLI (2)
    Prove Cauchy's inequality by induction
    纯数学教程 Page 325 例LXVIII (15) 调和级数发散
    纯数学教程 Page 325 例LXVIII (15) 调和级数发散
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/bzoj1001.html
Copyright © 2011-2022 走看看