http://poj.org/problem?id=2135
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define M 1100
const int inf=0x7fffffff;
struct node
{
int u,v,c,f,next; //C为花费,F为flow流量
} e[M*40];
int pre[M],dis[M],head[M],t;
int vis[M];
void add1(int u,int v,int c,int f)
{
e[t].u=u;
e[t].v=v;
e[t].c=c;
e[t].f=f;
e[t].next=head[u];
head[u]=t++;
}
void add(int u,int v,int c,int f)
{
add1(u,v,c,f);
add1(v,u,-c,0); //反向边流量初始为零,如果走反向边费用正好和原边抵消
}
int spfa(int s,int t)
{
int i,u,v;
queue<int>q;
q.push(s);
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
for(i=s; i<=t; i++)
dis[i]=inf;
dis[s]=0;
while(!q.empty())
{
u=q.front();
q.pop();
for(i=head[u]; i!=-1; i=e[i].next)
{
v=e[i].v;
if(e[i].f&&dis[v]>dis[u]+e[i].c) //找到一条最小费用流
{
dis[v]=dis[u]+e[i].c;
pre[v]=i; //记录路径
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
vis[u]=0;
}
if(dis[t]!=inf)
return 1;
return 0;
}
void solve(int s,int t)
{
int ans=0,i,j;
int flow=0,cost=0; //总流量、总费用
while(spfa(s,t))
{
int minf=inf;
for(i=pre[t]; i!=-1; i=pre[e[i].u])
{
if(e[i].f<minf)
minf=e[i].f;
}
flow+=minf; //该条路径的流量
for(i=pre[t]; i!=-1; i=pre[e[i].u])
{
j=i^1;
e[i].f-=minf;
e[j].f+=minf;
}
cost+=dis[t]*minf; //单位运费和乘以流量得费用
}
printf("%d\n",cost);
}
int main()
{
int i,u,v,c,n,m;
while(scanf("%d%d",&n,&m)!=-1)
{
t=0;
memset(head,-1,sizeof(head));
for(i=0; i<m; i++)
{
scanf("%d%d%d",&u,&v,&c); //边长度看做单位运费
add(u,v,c,1);
add(v,u,c,1); //无向边,费用为长度,流量为1(只能通过一次)
}
//往返的两条线路可以看成是从源点到汇点的两条线路,
//所以只要从附加源点向源点连一条容量为2的边和从汇点向附加汇点连一条容量为2的边就可以限线路为两条.
add(0,1,0,2);
add(n,n+1,0,2);
solve(0,n+1);
}
}