标签:
题意:恐怖分子计划将毒品从S城市运输到E城市,警察发现后准备在途中的城市全面封锁对他们进行逮捕,他们有很多路径可供选择从S到E,且路径是双向的,但是每次封锁需要花费,现在已知在每个城市进行封锁的花费,求最小的花费和。
由于给的权值不是在边上,而是在点上,所以需要进行割点处理:
最大流模板+拆点:
#include<stdio.h> #include<queue> #include<string.h> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; const int N=20010; struct node { int v, fee, next; }no[6*N]; int layer[N], head[N], k; void Add(int a, int b, int c) { no[k].v = b; no[k].fee = c; no[k].next = head[a]; head[a] = k++; swap(a, b); no[k].v = b; no[k].fee = 0; no[k].next = head[a]; head[a] = k++; } int BFS(int Start, int End) { int i, u, v; queue<int>Q; memset(layer, 0, sizeof(layer)); Q.push(Start); layer[Start] = 1; while (!Q.empty()) { u = Q.front(); Q.pop(); if (u == End) return 1; for (i = head[u]; i != -1; i = no[i].next) { v = no[i].v; if (no[i].fee && layer[v] == 0) { layer[v] = layer[u] + 1; Q.push(v); } } } return 0; } int DFS(int Start, int End, int mini) { int i, v, fee = 0, ans; if (Start == End) return mini; for (i = head[Start]; i != -1; i = no[i].next) { v = no[i].v; if (no[i].fee && layer[v] == layer[Start]+1) { ans = min(no[i].fee, mini-fee); ans = DFS(v, End, ans); no[i].fee -= ans; no[i+1].fee += ans; fee += ans; if (fee == mini) break; } } if (fee == INF) layer[Start] = 0; return fee; } int Dinic(int Start, int End) { int ans = 0; while (BFS(Start, End)) ans += DFS(Start, End, INF); return ans; } int main () { int n, m, i, S, E, ans, a, b, c; while (scanf("%d%d", &n, &m) != EOF) { memset(head, -1, sizeof(head)); k = 0; scanf("%d%d", &S, &E); for (i = 1; i <= n; i++) { scanf("%d", &c); Add(i, i+n, c); ///每个点i的权值现在保存到了i-i+n这条边上 } for (i = 1; i <= m; i++) { scanf("%d%d", &a, &b); Add(a+n, b, INF); Add(b+n, a, INF); ///保证每个点之间有回路,由于是双向,所以操作两次 } ans = Dinic(S, E+n); printf("%d\n", ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/syhandll/p/4727930.html