码迷,mamicode.com
首页 > 其他好文 > 详细

HDU-4289 Control(最小割,拆点)

时间:2019-08-10 21:22:11      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:bsp   get   display   void   flow   hid   pen   题目   ==   

题目链接:HDU-4289 Control

题意

恐怖分子计划将武器从城市$S$运输到城市$D$,现在我们知道$S$和$D$,知道城市网络中存在的路径(无向边),知道封锁每个城市各自需要的代价,我们可以对任意城市进行封锁,恐怖分子到达被封锁的城市就会被抓捕,求抓捕所有恐怖分子需要的最小代价。


思路

显然这是一个最小割问题,但代价是点权而不是边权,所以需要对每个城市结点拆成入点和出点,入点向出点连边,边权为对应城市结点的点权,这样就将点权代价转换为边权代价。不同城市之间的双向路径$(u,v)$,$u$的出点$u‘$向$v$的入点$v$连边,$v$的出点$v‘$向$u$的入点$u$连边,边权为无穷大,表示其不能作为割边。源点为$S$的入点,汇点为$D$的出点,跑最小割即可。


代码实现

技术图片
#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

 

HDU-4289 Control(最小割,拆点)

标签:bsp   get   display   void   flow   hid   pen   题目   ==   

原文地址:https://www.cnblogs.com/kangkang-/p/11332814.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!