求一条从s到t的回路,要求每条边只走一次,使总和最小。最小费用最大流。将每条边的流量设为1,答案就是最大流为2时的最小费用。
求最短路的时候用了SPFA。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<vector> #include<queue> #include<algorithm> #define MAXN 105 #define INF 2139062143 #define ll long long //ios::sync_with_stdio(false); using namespace std; int n; struct Edge { int to,from,cap,cost,rev; Edge(int a,int b,int c,int d,int e):to(a),from(b),cap(c),cost(d),rev(e) {} }; vector<Edge> gl[MAXN]; int prev[MAXN],pree[MAXN]; void add_edge(int to,int from,int cap,int cost) { gl[from].push_back(Edge(to,from,cap,cost,gl[to].size())); gl[to].push_back(Edge(from,to,0,-cost,gl[from].size()-1)); } void Init(int n) { for(int i=0; i<=n; ++i) gl[i].clear(); memset(prev,0,sizeof(prev)); memset(pree,0,sizeof(pree)); } int min_cost_flow(int s,int t,int f) { int res=0; while(f>0) { int dist[MAXN]; memset(dist,0x7f,sizeof(dist)); dist[s]=0; bool inque[MAXN]; memset(inque,0,sizeof(inque)); queue<int> que; que.push(s); inque[s]=true; while(!que.empty()) { int q=que.front(); que.pop(); inque[q]=false; for(int i=0; i<gl[q].size(); ++i) { Edge e=gl[q][i]; int to=e.to; if(e.cap>0&&dist[to]>dist[q]+e.cost) { dist[to]=dist[q]+e.cost; prev[to]=q; pree[to]=i; if(!inque[to]) { inque[to]=true; que.push(to); } } } } if(dist[t]==INF) return -1; int d=f; for(int i=t; i!=s; i=prev[i]) d=min(d,gl[prev[i]][pree[i]].cap); res+=d*dist[t]; f-=d; for(int i=t; i!=s; i=prev[i]) { int v=prev[i],e=pree[i]; gl[v][e].cap-=d; gl[i][gl[v][e].rev].cap+=d; } } return res; } int main() { while(scanf("%d",&n)&&n) { Init(n); int m; scanf("%d",&m); int x,y,z; while(m--) { scanf("%d%d%d",&x,&y,&z); add_edge(y,x,1,z); add_edge(x,y,1,z); } int ans=min_cost_flow(1,n,2); if(ans==-1) puts("Back to jail"); else printf("%d\n",ans); } return 0; }