标签: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; }
标签:bsp get display void flow hid pen 题目 ==
原文地址:https://www.cnblogs.com/kangkang-/p/11332814.html