/*
题意:有N个点的农场,之间有M条路径,问从起点走到到终点再走回起点的最短行走距离是多少,并且行走过程
中的路径不能有重复。
题解:最小费用最大流;
建图:建立无向图,边的权值均为1,保证路径只能走一次再分别加入源点和汇点,分别连接起点和终点,权值分
别为2,因为题目求的是一个来回的路径,亦即求从起点到终点的两条不重复路径即可。
从起点到终点再回起点其实是一个最大流的问题,由于还要使距离最短,因此在边加入一个值cost记录路径长度,
最小费用最大流求的是cost*权值的最小值,但是因为这个图中的所需求的权值均为1,因此直接用cost即可。最终
求最大流后将路径相加。
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define EMAX 500000
#define VMAX 1200
const int INF = 0xfffffff;
int head[VMAX],dis[VMAX],dist[VMAX],cur[VMAX],gap[VMAX],pre[VMAX],path[VMAX];
int EN;
struct edge
{
int to;
int weight;
int cost;
int next;
}e[EMAX];
void insert(int u,int v,int w, int c)
{
e[EN].to = v;
e[EN].weight = w;
e[EN].cost = c;
e[EN].next = head[u];
head[u] = EN++;
e[EN].to = u;
e[EN].weight = 0;
e[EN].cost = -c;
e[EN].next = head[v];
head[v] = EN++;
}
bool spfa(int start, int t)
{
memset(path,-1,sizeof(path));
memset(pre,-1,sizeof(pre));
bool vis[VMAX];
for(int i=0; i<=t; i++)
{
dist[i] = INF;
vis[i] = false;
}
queue<int> Q;
dist[start] = 0;
vis[start] = true;
Q.push(start);
while (!Q.empty())
{
int u = Q.front();
Q.pop();
for(int i=head[u]; i!=-1; i=e[i].next)
{
int v = e[i].to;
if (e[i].weight && dist[u]+e[i].cost < dist[v])
{
pre[v] = u;
path[v] = i;
dist[v] = dist[u]+e[i].cost;
if (!vis[v])
{
Q.push(v);
vis[v] = true;
}
}
}
vis[u] = false;
}
if (dist[t] == INF)
return false;
return true;
}
int mcmf(int s, int t)//最小费用最大流
{
queue<int> Q;
int ret = 0;
int maxflow = 0;
while (spfa(0,t))//每次通过spfa求最短的允许路
{
ret += dist[t];
int mw = -1;
for(int v=t; v!=s; v=pre[v])//找出当前路径中的流量的最小容量
{
if (mw == -1 || mw > e[path[v]].weight)
mw = e[path[v]].weight;
}
for(int v=t; v!=s; v=pre[v])//修改路径的容量,求出残余网络
{
e[path[v]].weight -= mw;
e[path[v]^1].weight += mw;//更新逆向边
}
maxflow += mw;
}
return ret;
}
int main(void)
{
int m,n,a,b,l;
while (~scanf("%d%d",&n,&m))
{
memset(head,-1,sizeof(head));
EN = 0;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&l);
insert(a,b,1,l);
insert(b,a,1,l);
}
insert(0,1,2,0);
insert(n,n+1,2,0);
printf("%d\n",mcmf(0,n+1));
}
return 0;
}