1.什么是最小费用最大流?
打个比方,这是一个运输过程,每条道路连接两座城市,每条路都有限重,也要按照货物数量收取过路费,问最多可以运多少货物。
2.怎么算?
和最大流算法很像,唯一不同的是需要加一个dis数组,然后将bfs改成SPFA即可。
3.注意事项
fa数组保存的是来到这个点的边。
在判断能不能走的时候不需要写fa[to[i]]==0了,在到达终点后也不能break了,因为我们可能要多次修改最小费用。
源点的初始流量为无限大。
4.代码
题目:poj2135
这不能跑两遍最短路,比如下面这组数据:
4 5 1 2 1 2 3 1 3 4 1 1 3 3 2 4 3 答案是8,但是如果你跑两遍最短路的话,第一次找到最短路1->2->3->4后就无法再走到终点了。 所以是求流量为2的网络流最小费用。 由于是无向图,所以每次要加两条正边两条反边。#include<iostream> #include<algorithm> #include<string> #include<vector> #include<cstdlib> #include<cstdio> #include<cstring> #include<queue> #include<climits> using namespace std; int n,m,sum=1,fy=0,ll=0; long long ans=0; int h[1005],to[40005],next[40005],cost[40005]; int fa[1005],que[3005];//fa应该记录的是来的那条路,而不是点,无向图! long long dis[1005]; bool can[40005],inq[1005]; void add(int x,int y,int z,int ta){ sum++;to[sum]=y;next[sum]=h[x];h[x]=sum;cost[sum]=z; can[sum]=ta; } bool bfs(){ int i,j,head=1,tail=1,from; memset(fa,0,sizeof(fa)); memset(inq,0,sizeof(inq)); memset(dis,127,sizeof(dis)); que[1]=1;inq[1]=1;dis[1]=0; while(head<=tail){ from=que[head]; inq[from]=0; for(i=h[from];i!=0;i=next[i]){ if(can[i]==1&&dis[to[i]]>dis[from]+cost[i]){//不要写fa[to[i]]==0 dis[to[i]]=dis[from]+cost[i];fa[to[i]]=i; if(inq[to[i]]==0){ tail++;que[tail]=to[i];inq[to[i]]=1; } } } head++; } if(fa[n]==0)return 0; return 1; } long long find(){ int i,x,last,cnt=0; ll=0; while(bfs()){ ans+=dis[n]; x=n; while(x!=1){ can[fa[x]]=0;can[fa[x]^1]=1; x=to[fa[x]^1];//如果是奇数,减1,如果是偶数,加1 } ll++; if(ll==2)break; } return ans; } int main() { int i,j,x,y,z; scanf("%d%d",&n,&m); for(i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z,1);add(y,x,-z,0);//1:可走 0:不可走 add(y,x,z,1);add(x,y,-z,0);//加两次边 } printf("%lld",find()); return 0; }