题意
- 给你一个无向图,问你从1号节点到n号节点,再从n号节点返回1号节点,且中间不走重复路的最短路径。
思路
- 开始的简单思路肯定是,先求一个最短路,再删除其中的边,然后再跑最短路。
- 问题是,这样贪心的话,会出现有两个条最短路,我们不知道选哪个好的情况~这样不行
- 我们想,用最小费用流来求解。
- 其实1->n和n->1对于无向图来说是没有区别的,那么我们是不是可以认为就是从1->n去两次,那么也就是流量为2
- 对于边,只能走一次,所以,我们认为边的容量限制是1,费用为边的长度
- 这样就是一个F=2的无向图最小费用流问题了
- 我们有有向图最小费用流模板,现在问题就是从无向图转向有向图
- 由于一条边不需要两个方向都有流量(因为就抵消了),所以我们只需要把一条无向边变为两条方向相反的有向边,且它俩的容量和花费与无向边的一致即可!
实现
#include <queue>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
const int INF = 0x3f3f3f3f;
struct MinCostFlow{
static const int MAX_V = 2000;
typedef pair<int,int> P;
struct edge{
int to, cap, cost, rev;
};
int V;
vector<edge> G[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V], preve[MAX_V];
void add_edge(int from, int to, int cap, int cost){
G[from].push_back((edge){to, cap, cost, G[to].size()});
G[to].push_back((edge) {from, 0, -cost, G[from].size() - 1 });
}
int min_cost_flow(int s, int t, int f){
int res = 0;
fill(h, h + V, 0);
while (f > 0){
priority_queue<P, vector<P>, greater<P> > que;
fill(dist, dist + V, INF);
dist[s] = 0;
que.push(P(0, s));
while (!que.empty()){
P p = que.top();
que.pop();
int v = p.second;
if (dist[v] < p.first)
continue;
for (int i = 0; i < G[v].size(); i++){
edge& e = G[v][i];
if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]){
dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
preve[e.to] = i;
que.push(P(dist[e.to], e.to));
}
}
}
if (dist[t] == INF){
return -f;
}
for (int v = 0; v < V; v++){
h[v] += dist[v];
}
int d = f;
for (int v = t; v != s; v = prevv[v]){
d = min(d, G[prevv[v]][preve[v]].cap);
}
f -= d;
res += d * h[t];
for (int v = t; v != s; v = prevv[v]){
edge &e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
}
void init(){
for (int i = 0; i < V; i++){
G[i].clear();
}
V = 0;
}
}mcf;
int n,m;
int main(){
scanf("%d%d",&n,&m);
mcf.V = n;
for (int i = 0;i < m;i++){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
mcf.add_edge(u-1, v-1, 1, c);
mcf.add_edge(v-1, u-1, 1, c);
}
printf("%d\n",mcf.min_cost_flow(0, n-1, 2));
return 0;
}