[BZOJ1001] [BeiJing2006]狼抓兔子(平面图dijkstra+heap;强大DINIC vs 辣鸡sap)

[BeiJing2006]狼抓兔子
  • 题意就是最小割.

  • 然后这里我打了Dinic,然后2000ms-过了,用普通的sap则超时....

  • 当然,此题还有一个平面图的解法,也是裸的.

  • 然后就可以学习一下dij+heap的版本,再学习一下逼格比较高的最大最小定理...

  • 棒棒哒~

  • dinic虐暴sap啊
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

#define I register int
#define F(i, a, b) for (I i = a; i <= b; i ++)
#define mem(a, b) memset(a, b, sizeof a)
#define Get getchar()

const int N = 1e6 + 5, M = N * 6;

using namespace std;

int n, m, x, tot, S, T, dis[N], ans;
int tov[M], nex[M], len[M], las[N];

void R(I &x) {
    char c = Get; x = 0; I t = 1;
    for (; !isdigit(c); c = Get) t = (c == '-' ? - 1 : t);
    for (; isdigit(c); x = (x << 3) + (x << 1) + c - '0', c = Get); x *= t;
}

int C(I x, I y) { return (x - 1) * m + y; }

void link(I x, I y, I L) {
    tov[++ tot] = y, nex[tot] = las[x], las[x] = tot, len[tot] = L;
    tov[++ tot] = x, nex[tot] = las[y], las[y] = tot, len[tot] = L;
}

bool bfs() {
    mem(dis, 0), dis[S] = 1;
    queue <int> Q; Q.push(S);
    while (!Q.empty()) {
        I k = Q.front(); Q.pop();
        for (I x = las[k]; x; x = nex[x])
            if (len[x] && !dis[tov[x]]) dis[tov[x]] = dis[k] + 1, Q.push(tov[x]);
    }
    return dis[T];
}

int dfs(I k, I flow) {
    if (k == T) return flow;
    I have = 0;
    for (I x = las[k]; x; x = nex[x])
        if (len[x] && dis[tov[x]] == dis[k] + 1) {
            I now = dfs(tov[x], min(flow - have, len[x]));
            have += now, len[x] -= now, len[x ^ 1] += now;
            if (have == flow) return have;
        }
    if (!have) dis[k] = - 1;
    return have;
}

int main() {
    R(n), R(m), tot = 1, S = 1, T = n * m;
    F(i, 1, n)  
        F(j, 1, m - 1) R(x), link(C(i, j), C(i, j + 1), x);
    F(i, 1, n - 1)
        F(j, 1, m) R(x), link(C(i, j), C(i + 1, j), x);
    F(i, 1, n - 1)
        F(j, 1, m - 1)
            R(x), link(C(i, j), C(i + 1, j + 1), x);
    
    while (bfs())
        ans += dfs(S, 1e9);
    
    printf("%d\n", ans);
}
  • 然后转为平面图,用最短路搞搞...

  • 实测:dijkstra+heap 2152ms ; spfa 3268ms

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

#define I register int
#define F(i, a, b) for (I i = a; i <= b; i ++)
#define mn(a, b) ((a) = (a) < (b) ? (a) : (b))
#define mem(a, b) memset(a, b, sizeof a)
#define Get getchar()

const int N = 2e6 + 10, M = 4 * N;

using namespace std;

int n, m, x, k, S, T, count, ans, dis[N]; bool vis[N];
int tov[M], nex[M], len[M], las[N], tot;
struct node {
    int u, dis;
    bool operator < (const node &a) const { return a.dis < dis; }
};

void R(I &x) {
    char c = Get; x = 0; I t = 1;
    for (; !isdigit(c); c = Get) t = (c == '-' ? - 1 : t);
    for (; isdigit(c); x = (x << 3) + (x << 1) + c - '0', c = Get); x *= t;
}

void link(I x, I y, I L) {
    tov[++ tot] = y, len[tot] = L, nex[tot] = las[x], las[x] = tot;
    tov[++ tot] = x, len[tot] = L, nex[tot] = las[y], las[y] = tot;
}

void dijkstra() {
    priority_queue<node> Q; mem(dis, 0x3f);
    Q.push({S, 0}), dis[S] = 0, count = 1;
    while (count --) {
        k = Q.top().u; Q.pop();
        if (vis[k]) continue; vis[k] = 1;
        for (x = las[k]; x; x = nex[x])
            if (dis[tov[x]] > dis[k] + len[x])
                dis[tov[x]] = dis[k] + len[x], Q.push({tov[x], dis[tov[x]]}), count ++;
    }
}
/*
void spfa() {
    queue<int> Q; Q.push(S), mem(dis, 0x3f);
    dis[S] = 0, count = 1, vis[S] = 1;
    while (count --) {
        k = Q.front(); Q.pop();
        for (x = las[k]; x; x = nex[x])
            if (dis[tov[x]] > dis[k] + len[x]) {
                dis[tov[x]] = dis[k] + len[x];
                if (!vis[tov[x]])
                    vis[tov[x]] = 1, Q.push(tov[x]), count ++;
            }
        vis[k] = 0;
    }
}*/

int main() {
    R(n), R(m), S = 0, T = ((n - 1) * (m - 1) << 1) + 1;
    
    if (n == 1 || m == 1)
    {
        if (n > m) swap(n, m); I ans = 1e9;
        F(i, 1, m - 1)
            R(x), mn(ans, x);
        printf("%d\n", ans);  return 0;
    }

    F(i, 1, m - 1)
        R(x), link(S, i, x);
    F(i, 2, n - 1)
        F(j, 1, m - 1) R(x), link((i - 2) * 2 * (m - 1) + (m - 1) + j, (i - 1) * 2 * (m - 1) + j, x);
    F(i, 1, m - 1)
        R(x), link((n - 2) * 2 * (m - 1) + (m - 1) + i, T, x);

    F(i, 1, n - 1) {
        R(x), link((i - 1) * 2 * (m - 1) + m, T, x);
        F(j, 2, m - 1)
            R(x), link((i - 1) * 2 * (m - 1) + j - 1, (i - 1) * 2 * (m - 1) + m + j - 1, x);
        R(x), link((i - 1) * 2 * (m - 1) + m - 1, S, x);
    }

    F(i, 1, n - 1)
        F(j, 1, m - 1)
            R(x), link((i - 1) * 2 * (m - 1) + j, (i - 1) * 2 * (m - 1) + m - 1 + j, x);
    
    dijkstra();
    
    //spfa();
    
    printf("%d", dis[T]);
}

猜你喜欢

转载自www.cnblogs.com/Pro-king/p/9383441.html