题目大意:
从起点1到终点N的一个圈,最小路径花费。完毕。
构图跑两次spfa,完毕。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#define NN 1111
#define MN 11111
using namespace std;
struct Edge{ int u,v,c,f,cost,next; }E[MN<<2];
int head[NN],dis[NN],cur[NN],pre[NN];
int EN,s,t;
bool vis[NN];
void addEdge( int u,int v,int c,int cost )
{
E[EN].v=v; E[EN].c=c; E[EN].f=0; E[EN].cost=cost;
E[EN].next=head[u]; head[u]=EN++;
E[EN].v=u; E[EN].c=0; E[EN].f=0; E[EN].cost=-cost;
E[EN].next=head[v]; head[v]=EN++;
}
void spfa()
{
memset( vis,0,sizeof(vis) );
memset( dis,0x3f,sizeof(dis) );
queue<int>Q;
dis[s]=0;pre[s]=s;
Q.push(s);
while( !Q.empty() )
{
int cc=Q.front();Q.pop();
vis[cc]=false;
for( int i=head[cc];i!=-1;i=E[i].next )
{
if( dis[E[i].v]>dis[cc]+E[i].cost && E[i].f<E[i].c )
{
dis[E[i].v]=dis[cc]+E[i].cost;
pre[E[i].v]=cc;
cur[E[i].v]=i;
if( !vis[E[i].v] )
{
Q.push(E[i].v);
vis[E[i].v]=true;
}
}
}
}
}
int main()
{
int N,M;
while( scanf("%d %d",&N,&M)!=EOF )
{
int u,v,cost;
memset( head,-1,sizeof(head) );
s=0;t=N+1;
for( int i=0;i<M;i++ )
{
scanf( "%d %d %d",&u,&v,&cost );
addEdge( u,v,1,cost );
addEdge( v,u,1,cost );
}
addEdge( s,1,2,0 ); addEdge( N,t,2,0 );
int ans=0;
while( true )
{
spfa();
int aug=0x3f3f3f3f;
if( dis[t]==0x3f3f3f3f )
break;
for( int i=t;i!=s;i=pre[i] )
aug=min( aug,E[cur[i]].c-E[cur[i]].f );
for( int i=t;i!=s;i=pre[i] )
{
E[cur[i]].f+=aug;
E[cur[i]^1].f-=aug;
}
ans+=aug*dis[t];
}
printf( "%d\n",ans );
}
return 0;
}