/**
题目来源:http://poj.org/problem?id=2135
题目翻译:FJ 的农场有N个地方,它的房子在位置1,在位置N有个大barn,FJ要带它的朋友
参观自己的农场,从1到N再从N到1,但是去和回来不能走同一段路,求去和回来的最短路
解题思路:题目可以用流量为2的最小费用流来解决,每条边的容量都设定为1,因为这样经
过一次增广后,被增广的边容量都会变成0.边的容量一旦变成0,就不能走了,刚好符合题目要求
再增广的时候,我们按照路径的花费最少的原则进行增广。
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 50000;
const LL inf = 4*1e9;
int N,M,S,T; ///N块地,M条边,S超级源点,T超级汇点
int head[maxn],cnt;
int vis[maxn],maxFlow,pre[maxn];
LL dist[maxn],minFlow,minCostMaxFlow;
struct Edge {
int from; ///起点
int to; ///终点
int cap; ///容量
LL cost; ///花费
int nex; ///下条边的位置
}edge[maxn];
///加边函数
void addEdge(int u,int v,LL cost) {
edge[cnt].from = u;
edge[cnt].to = v;
edge[cnt].cap = 1;
edge[cnt].cost = cost;
edge[cnt].nex = head[u];
head[u] = cnt++;
edge[cnt].from = v;
edge[cnt].to = u;
edge[cnt].cap = 0;
edge[cnt].cost = -cost;
edge[cnt].nex = head[v];
head[v] = cnt++;
}
///寻找最短增广路
bool spfa() {
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
for(int i = S; i <= T; i++) {
dist[i] = inf;
}
dist[S] = 0;
vis[S] = 1;
queue<int>qu;
qu.push(S);
while(!qu.empty()) {
int u = qu.front();
qu.pop();
vis[u] = 0;
for(int i = head[u]; i != -1; i = edge[i].nex) {
int v = edge[i].to;
if(edge[i].cap>0 && dist[u]+edge[i].cost<dist[v]) {
dist[v] = dist[u] + edge[i].cost;
pre[v] = i;
if(vis[v] == 0) {
vis[v] = 1;
qu.push(v);
}
}
}
}
if(dist[T] < inf) return true;
else return false;
}
void min_cost_max_flow() {
maxFlow = 0;
minCostMaxFlow = 0;
while(spfa()) {
minFlow = inf;
///这一部分可以不要,因为知道流量是1
for(int i = pre[T]; i != -1; i = pre[edge[i].from]) {
minFlow = min(minFlow,(LL)edge[i].cap);
}
for(int i = pre[T]; i != -1; i = pre[edge[i].from]){
edge[i].cap -= minFlow;
edge[i^1].cap += minFlow;
}
minCostMaxFlow += dist[T]*minFlow;
maxFlow += minFlow;
if(maxFlow == 2)
break;
}
}
int main() {
int u,v;
LL dis;
while(~scanf("%d%d",&N,&M)) {
S = 1;
T = N;
memset(head,-1,sizeof(head));
cnt = 0;
for(int i = 1; i <= M; i++) {
scanf("%d%d%lld",&u,&v,&dis);
addEdge(u,v,dis);
addEdge(v,u,dis);
}
min_cost_max_flow();
printf("%lld\n",minCostMaxFlow);
}
return 0;
}
题目