将编号为2~n-1的点拆为2个点,两点之间连一条边,容量为1,费用为0。注意入边连(i-1)*2,出边连(i-1)*2=1。不同之间容量为1。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<string>
#include<map>
#include<set>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<sstream>
#define LL long long
#define OJ_PRINT 0
#define READ_FILE 0
using namespace std;
const int NN_MAX = 5000;
const int MM_MAX = 50000;
const int INF = 0x1fffffff;
struct Edge{
int from,to,cap,flow,cost;
Edge (int a1=0,int b1=0,int c1=0,int d1=0,int e1=0):from(a1),to(b1),cap(c1),flow(d1),cost(e1){}
}theEdge[MM_MAX];
/**********************************************************/
int n,m,s,t;
vector<int>G[NN_MAX];
int lenEdge,mcost,mflow;
int d[NN_MAX],a[NN_MAX],inqee[NN_MAX],p[NN_MAX];
/**********************************************************/
int min_2 (int x,int y) {return x<y?x:y;}
int max_2 (int x,int y) {return x>y?x:y;}
bool mcmf ();
/**********************************************************/
int main()
{
if (READ_FILE) freopen ("in.txt","r",stdin);
while (scanf ("%d%d",&n,&m)!=EOF)
{
for (int i=0;i<NN_MAX;i++)
G[i].clear ();
lenEdge=0;
int a1,b1,c1;
for (int i=0;i<m;i++){
scanf ("%d%d%d",&a1,&b1,&c1);
if (a1!=n)
a1=(a1-1)*2+1;
else a1=(n-1)*2;
if (b1!=1)
b1=(b1-1)*2;
else b1=1;
theEdge[lenEdge++]=Edge (a1,b1,1,0,c1);G[a1].push_back (lenEdge-1);
theEdge[lenEdge++]=Edge (b1,a1,0,0,-c1);G[b1].push_back (lenEdge-1);
}
for (int i=2;i<n;i++){
a1=(i-1)*2;b1=(i-1)*2+1;
theEdge[lenEdge++]=Edge (a1,b1,1,0,0);G[a1].push_back (lenEdge-1);
theEdge[lenEdge++]=Edge (b1,a1,0,0,0);G[b1].push_back (lenEdge-1);
}
if (OJ_PRINT)
for (int i=0;i<lenEdge;i+=2)
printf ("%d %d\n",theEdge[i].from,theEdge[i].to);
s=1,t=2*(n-1),mcost=0,mflow=0;
while (mcmf ());
printf ("%d\n",mcost);
}
return 0;
}
bool mcmf ()
{
for (int i=0;i<=t;i++) d[i]=INF; d[s]=0;
memset (inqee,0,sizeof (inqee)); inqee[s]=1;
p[s]=0;a[s]=INF;
queue<int>qee;
qee.push (s);
while (!qee.empty ())
{
int x=qee.front ();qee.pop ();
inqee[x]=0;
for (int i=0;i<G[x].size ();i++){
Edge e=theEdge[G[x][i]];
if (e.cap>e.flow && d[e.to]>d[x]+e.cost){
d[e.to]=d[x]+e.cost;
a[e.to]=min_2 (a[x],e.cap-e.flow);
p[e.to]=G[x][i];
if (!inqee[e.to]){
qee.push (e.to);
inqee[e.to]=1;
}
}
}
}
if (d[t]==INF) return false;
mflow+=a[t];
mcost+=d[t]*a[t];
if (mflow==2) return false;
for (int i=t;i!=s;i=theEdge[p[i]].from){
theEdge[p[i]].flow+=a[t];
theEdge[p[i]^1].flow-=a[t];
}
return true;
}