重点讲一下每一条无向边变成2条有向边的正确性
(1)这样不会使本应无解的情况有解:一条边是S-->A->B-->T,另一条边是S从虚线到A,A->B,B从虚线到T,看似AB边走了2次,其实此时可以S-->A-->T, S-->B-->T,不走AB,确实有解。
(2)这样不会得到比正确的最小值更小的解。假如因为AB边走了2次而得到更小的解,那么同 (1)可以知道,不走AB的方法一定可以有更小的解(且合法)(因为cost一定是正的)
//#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<queue>
#include<assert.h>
#include<stack>
using namespace std;
const int maxn = 100+ 5;
const int INF = 1e9;
struct edge
{
int from, to, cap, flow, cost;
};
struct MCMF
{
int inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn];
int n, m;
vector<int> G[maxn];
vector<edge> edges;
void init(int n)
{
this->n = n;
for (int i = 0; i <= n; i++)G[i].clear();
edges.clear();
}
void add_edge(int from, int to, int c, int cost)
{
edges.push_back(edge{ from,to,c,0,cost });
edges.push_back(edge{ to,from,0,0,-cost });
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool bellmanford(int s, int t, int& flow, int& cost)
{
for (int i = 0; i <= n; i++)d[i] = INF;
d[s] = 0; inq[s] = 1; a[s] = INF;
queue<int> q; q.push(s);
while (!q.empty())
{
int x = q.front(); q.pop();
inq[x] = 0;
for (int i = 0; i < G[x].size(); i++)
{
edge& e = edges[G[x][i]];
int v = e.to;
if (e.cap > e.flow && d[v] > d[x] + e.cost)
{
d[v] = d[x] + e.cost;
p[v] = G[x][i];
a[v] = min(a[x], e.cap - e.flow);
if (!inq[v])
{
inq[v] = 1; q.push(v);
}
}
}
}
if (d[t] == INF)return 0;
flow += a[t];
cost += (a[t] * d[t]);
int v = t;
while (v != s)
{
edges[p[v]].flow += a[t];
edges[p[v] ^ 1].flow -= a[t];
v = edges[p[v]].from;
}
return 1;
}
int mincost(int s, int t,int& flow)
{
flow = 0; int cost = 0;
while(bellmanford(s,t,flow,cost)){}
return cost;
}
}mc;
int n,m;
int main()
{
while (cin >> n&&n)
{
mc.init(n);
cin >> m;
for (int i = 0; i < m; i++)
{
int u, v, d; cin >> u >> v >> d;
mc.add_edge(u, v, 1, d);
mc.add_edge(v, u, 1, d);
}
mc.add_edge(0, 1, 2, 0);
int flow = 0;
int cost=mc.mincost(0, n,flow);
if (flow < 2)
{
cout << "Back to jail" << endl;
}
else
{
cout << cost << endl;
}
}
return 0;
}