1. 程式人生 > >uva 10806 Dijkstra, Dijkstra. (最小費最大流)

uva 10806 Dijkstra, Dijkstra. (最小費最大流)

content clu cap from down 必須 正向 push_back 最大流

uva 10806 Dijkstra, Dijkstra.

題目大意:你和你的夥伴想要越獄。你的夥伴先去探路,等你的夥伴到火車站後,他會打電話給你(電話是藏在蛋糕裏帶進來的),然後你就能夠跑去火車站了,那裏有人接應你。

可是。由於你的夥伴跑去火車站的時候穿的是囚服,所以,他經過的街道都被戒嚴了,你必須從其它街道跑過去。

假設你能夠到達火車站,請輸出你和你的夥伴在路上花費的最短時間,假設不能請“Back to jail”。

解題思路:最小費最大流。設置一個超級源點連向監獄(起點1), 容量為2(兩個人),設置一個超級匯點,使火車站(終點n)連向他,容量為2(兩個人)。其余街道皆為無向(即正向反向都要考慮)。且容量為1(每條街道僅僅能跑一次)。最後求最大流,若最大流為2則輸出最小費,否則回監獄準備下次越獄吧。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 105;
const int INF = 0x3f3f3f3f;
int n, m, s, t;
int a[N], pre[N], d[N], inq[N]; 

struct Edge{
    int
from, to, cap, flow; ll cos; }; vector<Edge> edges; vector<int> G[3 * N]; void init() { for (int i = 0; i < 3 * N; i++) G[i].clear(); edges.clear(); } void addEdge(int from, int to, int cap, int flow, ll cos) { edges.push_back((Edge){from, to, cap, 0, cos}); edges.push_back((Edge){to, from, 0
, 0, -cos}); int m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); } void input() { int from, to; ll cost; for (int i = 0; i < m; i++) { scanf("%d %d %lld", &from, &to, &cost); addEdge(from, to, 1, 0, cost); addEdge(to, from, 1, 0, cost); } addEdge(0, 1, 2, 0, 0); addEdge(n, n + 1, 2, 0, 0); } int BF(int s, int t, int& flow, ll& cost) { queue<int> Q; memset(inq, 0, sizeof(inq)); memset(a, 0, sizeof(a)); memset(pre, 0, sizeof(pre)); for (int i = 0; i <= 2 * n + 1; i++) d[i] = INF; d[s] = 0; a[s] = INF; inq[s] = 1; int flag = 1; pre[s] = 0; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = 0; for (int i = 0; i < G[u].size(); i++) { Edge &e = edges[G[u][i]]; if (e.cap > e.flow && d[e.to] > d[u] + e.cos) { d[e.to] = d[u] + e.cos; a[e.to] = min(a[u], e.cap - e.flow); pre[e.to] = G[u][i]; if (!inq[e.to]) { inq[e.to] = 1; Q.push(e.to); } } } flag = 0; } if (d[t] == INF) return 0; flow += a[t]; cost += (ll)d[t] * (ll)a[t]; for (int u = t; u != s; u = edges[pre[u]].from) { edges[pre[u]].flow += a[t]; edges[pre[u]^1].flow -= a[t]; } return 1; } int MCMF(int s, int t, ll& cost) { int flow = 0; cost = 0; while (BF(s, t, flow, cost)); return flow; } int main() { while (scanf("%d", &n) != EOF) { if (n == 0) break; scanf("%d", &m); s = 0, t = n + 1; init(); input(); ll cost = 0; int ans = MCMF(s, t, cost); if (ans == 1) printf("Back to jail\n"); else printf("%lld\n", cost); } return 0; }

uva 10806 Dijkstra, Dijkstra. (最小費最大流)