poj 2135 最小费用流
#include<stdio.h> #include<string.h> #include<algorithm> #include<queue> using namespace std; #define SIZE 1010 const int inf = 100000000; struct node{ int s,t,f,w; int next; }edge[100010]; int head[2010]; int mincost,tot; int s,t,pre[2010]; void add(int s,int t,int w,int f) { edge[tot].f=f; edge[tot].w=w; edge[tot].t=t; edge[tot].s=s; edge[tot].next=head[s]; head[s]=tot++; } void addedge(int s,int t,int w,int f) { add(s,t,w,f); add(t,s,-w,0); } int n; bool spfa() { bool vis[SIZE]; memset(vis,false,sizeof(vis)); int d[SIZE]; int i=n+2; while(i--)d[i]= inf; d[s]=0; vis[s]=true; queue<int >Q; Q.push(s); pre[s]=-1; while(!Q.empty()) { int u=Q.front(); Q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=edge[i].next) { if(edge[i].f>0&&d[u]+edge[i].w<d[edge[i].t]) { d[edge[i].t]=d[u]+edge[i].w; pre[edge[i].t]=i; if(!vis[edge[i].t]) { Q.push(edge[i].t); vis[edge[i].t]=true; } } } } if(d[t]==inf) return false; return true; } void solve() { for(int i=pre[t];i!=-1;i=pre[edge[i].s]) { edge[i].f-=1; edge[i^1].f+=1; mincost+=edge[i].w; } } int main() { int m,cases=1; while(scanf("%d%d",&n,&m),(n||m)) { s=0;t=n+1; tot=0; mincost=0; memset(head,-1,sizeof(head)); for(int i=0;i<m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); a++,b++; addedge(a,b,c,1); addedge(b,a,c,1); } addedge(s,1,0,2); addedge(n,t,0,2); while(spfa()) { solve(); } printf("%d\n",mincost); } return 0; }
从起点走到终点,再从终点走到起点,不能有重复的路径
不能单纯的求最短路径两遍,因为第一次选的点会影响第二次走最短路的选择
因为每条边只能选一次,所以给每条边一个容量1,即只能流一次,费用为路径的长度
然后利用最小费用流来求解