# Poj - 2135 Farm Tour (网络流-最小费用最大流)

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<functional>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = (int)2e5 + 50;
typedef pair<int, int>P; //first->最短路距离  second->顶点编号
struct edge {
int to, cap, cost, rev;
};
int V;//顶点数
vector<edge>G[maxn];
int h[maxn];  //顶点的势，用来避免负环的出现
int dist[maxn];//最短距离
int prevv[maxn], preve[maxn];//最短路的前驱结点和对应的边
void add(int from, int to, int cap, int cost) {
edge ee;
ee.to = to, ee.cap = cap, ee.rev = G[to].size(), ee.cost = cost;
G[from].push_back(ee);
ee.to = from, ee.cap = 0, ee.rev = G[from].size() - 1, ee.cost = -cost;
G[to].push_back(ee);
}
int min_cost_flow(int s, int t, int f) {
int res = 0;
fill(h, h + V, 0);//初始化h
while (f > 0) {
//使用Dijkstra算法更新h
priority_queue<P, vector<P>, greater<P> >q; //greater需要<functional>头文件,注意> >中间要加" "
fill(dist, dist + V, inf);
dist[s] = 0;
q.push(P(0, s));
while (!q.empty()) {
P p = q.top(); q.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;
q.push(P(dist[e.to], e.to));
}
}
}
if (dist[t] == inf)//不能再增广
return -1;
for (int v = 0; v < V; v++)
h[v] += dist[v];
//沿s->t的最短路尽量增广
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;
}
int main() {
int m, u, v, w;
while (~scanf("%d%d", &V, &m)) {
while (m--) {
scanf("%d%d%d", &u, &v, &w);
u--, v--;
add(u, v, 1, w);
add(v, u, 1, w);
}
printf("%d\n", min_cost_flow(0, V - 1, 2));//这个是从0到v-1的
}
return 0;
}