HDU-4289 Control (minimum cut, split point)

Topic links: HDU-4289 Control

The meaning of problems

Terrorists planned weapons from city to city transportation $ S $ $ D $, and now we know that $ S $ and $ D $, know the city exists in the network path (undirected edges), know their needs each city block cost we can carry out any blockade of the city, reaching the blockaded city of terrorists will be arrested, seeking to arrest all the terrorists minimum cost required.


Thinking

This is obviously a minimum cut problem, but the price point is right instead of right side, so it needs an overhaul for each node into the city and out points, a point to point even side, the right side of the node corresponding city right point, this point will be converted into the right side of the price right price. Bidirectional path $ (u, v) $, $ u $ $ u between points out the different cities 'to $ $ $ $ v $ v connected to the edge point, Out point $ v $ v $' $ $ to the point $ u $ u $ even side, the right side is infinite, it can not be expressed as a cutting edge. S $ $ source is a point, $ D $ sink point of a point, the minimum run can be cut.


Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using std::queue;
const int INF = 0x3f3f3f3f, N = 500, M = 100000;
int head[N], d[N];
int s, t, tot, maxflow;
struct Edge
{
    int to, cap, nex;
} edge[M];
queue<int> q;
void add(int x, int y, int z) {
    edge[++tot].to = y, edge[tot].cap = z, edge[tot].nex = head[x], head[x] = tot;
    edge[++tot].to = x, edge[tot].cap = 0, edge[tot].nex = head[y], head[y] = tot;
}
bool bfs() {
    memset(d, 0, sizeof(d));
    while (q.size()) q.pop();
    q.push(s); d[s] = 1;
    while (q.size()) {
        int x = q.front(); q.pop();
        for (int i = head[x]; i; i = edge[i].nex) {
            int v = edge[i].to;
            if (edge[i].cap && !d[v]) {
                q.push(v);
                d[v] = d[x] + 1;
                if (v == t) return true;
            }
        }
    }
    return false;
}
int dinic(int x, int flow) {
    if (x == t) return flow;
    int rest = flow, k;
    for (int i = head[x]; i && rest; i = edge[i].nex) {
        int v = edge[i].to;
        if (edge[i].cap && d[v] == d[x] + 1) {
            k = dinic(v, std::min(rest, edge[i].cap));
            if (!k) d[v] = 0;
            edge[i].cap -= k;
            edge[i^1].cap += k;
            rest -= k;
        }
    }
    return flow - rest;
}
void init() {
    tot = 1, maxflow = 0;
    memset(head, 0, sizeof(head));
}

int main() {
    int n, m;
    while (~scanf("%d %d", &n, &m)) {
        init();
        scanf("%d %d", &s, &t);
        t += n;
        for (int i = 1, val; i <= n; i++) {
            scanf("%d", &val);
            add(i, i + n, val);
        }
        for (int i = 0, u, v; i < m; i++) {
            scanf("%d %d", &u, &v);
            add(u + n, v, INF);
            add(v + n, u, INF);
        }
        while (bfs()) maxflow += dinic(s, INF);
        printf("%d\n", maxflow);
    }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/kangkang-/p/11332814.html