HYSBZ - 1001 狼抓兔子(对偶图+最短路)

题目大意:给出一张图,这张图的每条边都有相应的容量,现在问,从(1,1)到(N,M)的最小割是多少

解题思路:转成对偶图去解决

#include 
#include 
#include 
#include 
using namespace std;
const int MAXNODE = 1000010;
const int MAXEDGE = MAXNODE * 6;
const int INF = 0x3f3f3f3f;

struct Edge{
    int v, val, next;
    Edge() {}
    Edge(int v, int val, int next): v(v), val(val), next(next) {}
}E[MAXEDGE];

struct Node {
    int v, val;
    Node() {}
    Node(int v, int val): v(v), val(val) {}
    bool operator <(const Node &a) const {
        return val > a.val;
    }
};

int n, m, tot, source, sink;
int head[MAXNODE * 2], d[MAXNODE * 2];
bool vis[MAXNODE * 2];

void AddEdge(int u, int v, int cap) {
    E[tot] = Edge(v, cap, head[u]);
    head[u] = tot++;
    u = u ^ v; v = u ^ v; u = u ^ v;
    E[tot] = Edge(v, cap, head[u]);
    head[u] = tot++;
}

void Dijkstra() {
    for (int i = 1; i <= sink; i++) {
        d[i] = INF; vis[i] = false;
    }
    d[source] = 0;
    priority_queue Q;
    Q.push(Node(source, 0));

    while (!Q.empty()) {
        int u = Q.top().v; Q.pop();
        if (vis[u]) continue;
        vis[u] = true;
        for (int i = head[u]; ~i; i = E[i].next) {
            int v = E[i].v;
            if (d[v] > d[u] + E[i].val) {
                d[v] = d[u] + E[i].val;
                Q.push(Node(v, d[v]));
            }
        }
    }
    printf("%d\n", d[sink]);
}

void solve() {
    source = (n - 1) * (m - 1) * 2 + 1, sink = source + 1;
    memset(head, -1, sizeof(head));
    tot = 0;
    int Min = INF;

    int val, u, v;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m - 1; j++) {
            scanf("%d", &val);
            Min = min(Min, val);
            if (i == 1) AddEdge(j * 2, sink, val);
            else if (i != n) {
                u = 1 + (i - 2) * 2 * (m - 1) + (j - 1) * 2;
                v = u + 2 * (m - 1) + 1;
                AddEdge(u, v, val);
            }
            else AddEdge(source, 1 + (n - 2) * (m - 1) * 2 + (j - 1) * 2, val);
        }
    }

    for (int i = 1; i <= n - 1; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &val);
            Min = min(Min, val);
            if (j == 1) AddEdge(source, 1 + (i - 1) * (m - 1) * 2, val);
            else if (j != m) {
                u = 2 + (i - 1) * (m - 1) * 2 + (j - 2) * 2;
                v = u + 1;
                AddEdge(u, v, val);
            }
            else AddEdge(i * (m - 1) * 2, sink, val);
        }
    }

    for (int i = 1; i <= n - 1; i++)
        for (int j = 1; j <= m - 1; j++) {
            scanf("%d", &val);
            Min = min(Min, val);
            u = 1 + (i - 1) * (m - 1) * 2 + (j - 1) * 2;
            v = u + 1;
            AddEdge(u, v, val);
        }
    if (n <= 1 && m <= 1) 
        printf("0\n");
    else if (n == 1 || m == 1)
        printf("%d\n", Min);
    else Dijkstra();
}

int main() {
    while (~scanf("%d%d", &n, &m)) solve();
    return 0;
}

你可能感兴趣的:(ACM-图论-最短路,ACM-图论-网络流)