HDU - 3870 Catch the Theves(最小割+对偶图==最短路)

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

解题思路:转成对偶图,就可以用最短路了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;
const int MAXNODE = 160010;
const int MAXEDGE = MAXNODE * 4;
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, source, sink, tot;
int d[MAXNODE], head[MAXNODE];
bool vis[MAXNODE];

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 init() {
    scanf("%d", &n);
    memset(head, -1, sizeof(head));
    tot = 0;

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

    for (int i = 1; i < n - 1; i++)  {
        scanf("%d", &val);
        AddEdge(i * (n - 1) + 1, source, val);
        AddEdge(i * (n - 1) + 1, (n - 1) * (i - 1) + 1, val);
        for (int j = 2; j < n; j++) {
            scanf("%d", &val);
            AddEdge(i * (n - 1) + j, i * (n - 1) + j - 1, val);
            AddEdge(i * (n - 1) + j, (i - 1) * (n - 1) + j, val);
        }
        scanf("%d", &val);
        AddEdge((i + 1) * (n - 1), sink, val);
    }

    for (int i = 1; i <= n; i++) {
        scanf("%d", &val);
        if (i != n) AddEdge((n - 1) * (n - 2) + i, source, val);
    }
}

void Dijkstra() {
    for (int i = 1; i <= sink; i++) {
        d[i] = INF; vis[i] = false;
    }

    d[source] = 0;
    priority_queue<Node> 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]);
}

int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        init();
        Dijkstra();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值