题目地址:POJ 2135
来回走一遍可以看成从源点到汇点走两遍。将每个点的流量设为1,就可以保证每条边不重复。然后跑一次费用流就行了。当流量到了2之后停止,输出此时的费用。
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; int head[1100], source, sink, cnt, cost, flow; int d[1100], vis[1100], cur[1100]; struct node { int u, v, cap, cost, next; }edge[100000]; void add(int u, int v, int cap, int cost) { edge[cnt].v=v; edge[cnt].cap=cap; edge[cnt].cost=cost; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].cap=0; edge[cnt].cost=-cost; edge[cnt].next=head[v]; head[v]=cnt++; } int spfa() { memset(d,INF,sizeof(d)); memset(vis,0,sizeof(vis)); queue<int>q; q.push(source); d[source]=0; cur[source]=-1; int minflow=INF, i; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(d[v]>d[u]+edge[i].cost&&edge[i].cap) { d[v]=d[u]+edge[i].cost; minflow=min(minflow,edge[i].cap); cur[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } if(d[sink]==INF) return 0; flow+=minflow; cost+=minflow*d[sink]; //printf("%d\n",minflow); if(flow==2) return 0; for(i=cur[sink];i!=-1;i=cur[edge[i^1].v]) { edge[i].cap-=minflow; edge[i^1].cap+=minflow; } return 1; } void mcmf() { while(spfa()) ; printf("%d\n",cost); } int main() { int n, m, i, u, v, w; scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); cnt=0; source=1; sink=n; cost=0; flow=0; while(m--) { scanf("%d%d%d",&u,&v,&w); add(u,v,1,w); add(v,u,1,w); } mcmf(); return 0; }