/*
题意: 一个无向图, 边的权是长度,要求从1到n, 再从n回到1的最短路长, 每条路只能走一次.
明显是求最小环,n范围是1000,明显用floyd求最小环是不明智的, 因为从分类中知道这题是最小费用流, 所以为了不陷入这种固定思维,就很自然的往最小环和最短路,接着是最大流,发现越想越复杂, 最终还是想回费用流, 很快就想到构图了.. 从起点到终点的最短路和从终点到起点的最短路是一样的,所以可以看成从源点拉两条路到汇点,所以流入汇点和流出源点的容量都是2.
构图: 长度为费用,每条边流为1, 增加源点连容量2,费用0边到1, n连汇点,容量2,费用0, 直接求最小费用
注: wa了很久, 注意是双向边,没重边,也不会超出int
*/
#define typef int //type of flow
#define typec int //type of dis
const typef inff = 0x3f3f3f3f; //max of flow
const typec infc = 0x3f3f3f3f; //max of dis
const int N = 1100;
const int E = 40010;
struct network{
int nv, ne, pnt[E];
int nxt[E]; //next, 保存的是pnt中下标
int vis[N],que[N];
int head[N]; //链表头
int pv[N]; //前驱节点
int pe[N];
typef flow,cap[E];//cap为当前流
typec cost,dis[E],d[N];
void addedge(int u,int v,typef c,typec w)
{
pnt[ne]= v;
cap[ne] = c;
dis[ne] =+w;
nxt[ne] =head[u];
head[u] =(ne++);
pnt[ne] = u;
cap[ne] = 0;
dis[ne] = -w;
nxt[ne] =head[v];
head[v] =ne++;
}
typec mincost(int src,int sink) //原点和会终点
{
int i,k;
int f,r;//队列指针,f为开头,r为结尾
typef mxf;
for(flow=0,cost=0;;)
{
memset(pv,-1,sizeof(pv));
memset(vis,0,sizeof(vis));
for(i=0;i<nv;i++) d[i]=infc;//球最长路时路径初始化为-1
d[src] = 0;
pv[src] = src;
vis[src] = 1;
for(f=0,r=1,que[0]=src;r!=f;)
{
i=que[f++];
vis[i]=0;
if(N==f)f=0;//循环队列
for(k = head[i];k!=-1;k=nxt[k])
if(cap[k]&&dis[k]+d[i]<d[pnt[k]])
{
d[pnt[k]]=dis[k]+d[i];
if(0 == vis[pnt[k]])
{
vis[pnt[k]]=1;
que[r++] = pnt[k];
if(N == r)r=0;
}
pv[pnt[k]]=i;
pe[pnt[k]]=k;
}
}
if(-1 == pv[sink]) break;
for(k=sink,mxf = inff;k != src;k=pv[k])
if(cap[pe[k]]< mxf) mxf = cap[pe[k]];
flow+= mxf;
cost+=d[sink]*mxf;
for(k= sink;k!=src;k=pv[k])
{
cap[pe[k]]-=mxf;
cap[pe[k]^1]+=mxf;
}
}
return cost;
}
void build()
{
ne = 0;
memset(head,-1,sizeof(head));
int x,y;
typef f;
typec w;
int n,m,u,v,i;
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&w);
addedge(x,y,1,w);
addedge(y,x,1,w);
}
addedge(0,1,2,0);
addedge(n,n+1,2,0);
nv=n+2;
}
}g;
int main()
{
g.build();
printf("%d/n",g.mincost(0,g.nv-1));
}