http://poj.org/problem?id=2135
此题中的费用是路径长度,流量是经过的点的数目(流量越大对应于更好地参观农场),因此是一个最小费用最大流问题,使用SPFA来求解。
AC代码:
#include <queue>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1010;
const int MAXM = 1000010;
const int INF = 0x3f3f3f3f;
int sumFlow,S,T,n,m;
int NE,head[MAXN],dis[MAXN],pre[MAXN],vis[MAXN];
struct edge{
int u,v,c,w;
int next;
}node[MAXM<<2];
void Init(){
NE = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int c, int w){//前向弧与后向弧
node[NE].v = v;
node[NE].u = u;
node[NE].c = c;
node[NE].w = w;
node[NE].next = head[u];
head[u] = NE++;
node[NE].v = u;
node[NE].u = v;
node[NE].c = 0;
node[NE].w = -w;
node[NE].next = head[v];
head[v] = NE++;
}
bool SPFA(){
queue <int> Q;
memset(vis, 0, sizeof(vis));
memset(pre, -1, sizeof(pre));
memset(dis, 0x3f, sizeof(dis));
vis[S] = 1, dis[S] = 0;
Q.push(S);
while(!Q.empty()){
int u = Q.front();
Q.pop();
vis[u] = 0;
for(int i=head[u]; i!=-1; i=node[i].next){
int v = node[i].v;
if(node[i].c > 0 && dis[v] > dis[u] + node[i].w){
dis[v] = dis[u] + node[i].w;
pre[v] = i;
if(!vis[v]){
Q.push(v);
vis[v] = 1;
}
}
}
}
if(dis[T] == INF) return false;
return true;
}
int MCMF(){
int flow = 0;
int mincost = 0;
while(SPFA()){
int minflow = INF;
for(int i=pre[T]; i!=-1; i=pre[node[i].u])
if(node[i].c < minflow)
minflow = node[i].c;
flow += minflow;
for(int i=pre[T]; i!=-1; i=pre[node[i].u]){
node[i].c -= minflow;
node[i^1].c += minflow;
}
mincost += dis[T] * minflow;
}
sumFlow = flow;
return mincost;
}
int main(){
while(scanf("%d%d",&n,&m) == 2){
Init();
S = 0, T = n+1;
while(m--){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,1,w);
addedge(v,u,1,w);
}
addedge(S,1,2,0);
addedge(n,T,2,0);
int ans = MCMF();
printf("%d\n",ans);
}
return 0;
}