就是从1走到n然后再走回来,一条边只能走一次,要求路径最短。
// MCMF 最小费用最大流
#include <cstdio>
#include <vector>
#include <string>
#include <string.h>
#include <queue>
#define MAX 1000 + 5
#define INF 0x3fffffff
using namespace std;
struct Edge {
int from, to, cap, flow, cost;
Edge( int u, int v, int ca, int f, int co ) : from(u),to(v),cap(ca),flow(f),cost(co){};
};
int n,m,s,t;
vector<Edge> edges;
vector<int> G[MAX];
int inq[MAX];//是否在队列中
int d[MAX];//距离
int p[MAX];//上一条弧
int a[MAX];//可改进量
void init( int n ) {//初始化
for( int i = 0; i < n; i++ )
G[i].clear();
edges.clear();
}
void addEdge( int from, int to, int cap, int cost ) { //加边
edges.push_back( Edge( from, to, cap, 0, cost ) );
edges.push_back( Edge( to, from, 0, 0, -cost ) );
int m = edges.size();
G[from].push_back( m - 2 );
G[to].push_back( m - 1 );
}
bool SPFA( int s, int t, int &flow, int &cost ) { //寻找最小费用的增广路,使用引用同时修改原flow,cost
fill( d, d + MAX, INF );
memset( inq, 0, sizeof( inq ) );
// 源点入队部分
d[s] = 0;
inq[s] = 1;
p[s] = 0;
a[s] = INF;
queue<int> q;
q.push( s );
while( !q.empty () ) {
int u = q.front();
q.pop();
inq[u]--;
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.cost ) { //满足可增广且可变短
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min( a[u], e.cap - e.flow );
if( !inq[e.to] ) {
inq[e.to]++;
q.push(e.to);
}
}
}
}
if( d[t] == INF ) return false; //汇点不可达则退出
flow += a[t];
cost += d[t] * a[t];
int u = t;
while( u != s ) { //更新正向边和反向边
edges[p[u]].flow += a[t];
edges[p[u] ^ 1].flow -= a[t];
u = edges[p[u]].from;
}
return true;
}
int MincotMaxflow( int s, int t, int cnt ) {
int flow = 0, cost = 0;
//while( SPFA( s, t, flow, cost ) );
while( cnt > 0 ) {
SPFA( s, t, flow, cost );
cnt--;
}
return cost;
}
int main() {
int a, b, c;
while( ~scanf( "%d%d", &n, &m ) ) {
init( n );
for( int i = 0; i < m; i++ ) {
scanf( "%d%d%d", &a, &b, &c );
addEdge( a - 1, b - 1, 1, c );
addEdge( b - 1, a - 1, 1, c );
}
printf( "%d\n", MincotMaxflow( 0, n - 1, 2 ) );
}
return 0;
}