【网络流#9】POJ 2135 Farm Tour 最小费用流 - 《挑战程序设计竞赛》例题
【题意】给出一张无向图,从1开始到n,求两条没有公共边的最短路,使得路程总和最小
每条边的权值设为费用,最大流量设为1,然后就是从源点到汇点流量为2的最小费用流。
因为是规定了流量,新建一个源点和一个汇点,源点到结点1连一条最大流量为2,费用为0的边,结点N到汇点连一条最大流量为2,费用为0的边,这样就规定好流量了。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<stack> #include<vector> #include<queue> #include<string> #include<sstream> #define eps 1e-9 #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define FOR(i,j,k) for(int i=j;i<=k;i++) #define MAXN 1005 #define MAXM 40005 #define INF 0x3fffffff using namespace std; typedef long long LL; int i,j,k,n,m,x,y,ans,big,cas,num,w,t,u,v,S,T; bool flag; int head[MAXN],vis[MAXN],dis[MAXN],pos[MAXN],Edge,size; char s[305][305]; struct edgenode { int to,next,w,cost; } edge[MAXM]; void add_edge(int x,int y,int w,int cost) { edge[Edge].to=y; edge[Edge].w=w; edge[Edge].cost=cost; edge[Edge].next=head[x]; head[x]=Edge; Edge++; edge[Edge].to=x; edge[Edge].w=0; edge[Edge].cost=-cost; edge[Edge].next=head[y]; head[y]=Edge; Edge++; } bool SPFA(int s, int t) { int u,v,i; queue <int> q; memset(vis,0,sizeof(vis)); for(i=0;i<size;i++) dis[i]=INF; dis[s]=0; vis[s]=1; q.push(s); while(!q.empty()) { u=q.front(); q.pop(); vis[u]=0; for (i=head[u];i!=-1;i=edge[i].next) { v=edge[i].to; if(edge[i].w>0&&dis[u]+edge[i].cost<dis[v]) { dis[v]=dis[u]+edge[i].cost; pos[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } return dis[t]!=INF; } int MinCostFlow(int s,int t) { int i,cost=0,flow=0; while(SPFA(s,t)) { int d=INF; for (i=t;i!=s;i=edge[pos[i]^1].to) { d=min(d,edge[pos[i]].w); } for(i=t;i!=s;i=edge[pos[i]^1].to) { edge[pos[i]].w-=d; edge[pos[i]^1].w+=d; } flow+=d; cost+=dis[t]*d; } return cost; // flow是最大流值 } int main() { memset(head,-1,sizeof(head));Edge=0; scanf("%d%d",&n,&m); for (i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&t); add_edge(x,y,1,t); add_edge(y,x,1,t); } S=0;T=n+1; size=n+2; add_edge(S,1,2,0); add_edge(n,T,2,0); printf("%d\n",MinCostFlow(S,T)); return 0; }