最小费用最大流--poj2135

来源:互联网 发布:photoshop mac版价格 编辑:程序博客网 时间:2024/05/16 12:38

对于最下费用最大流,很久以前就已经学习过了,但是却早已经不记得了。
于是今天就来重新的复习一下。
对于最小费用最大流,我一直都有疑问,不知道是否有没有更高效的做法。
下面还是来简单的概述一下最小费用最大流的基本操作。
对于本题,建模并不是很难—-只需要新建一个超级源点和超级汇点即可。
图中除了与超级源点和超级汇点连接的是有向图且容量为2,权值为0.其他的点均为无向图,且容量为1.(想一想,为什么?)
这样简单的模型就建立了。
而最小费用最大流有点像最大流的做法,不断的寻找增广路,只是这个增广路是最短路,在流量允许的情况下,尽量的寻找最短路,然后不断地更新流量和最短路。有点像EK啊!

#include<iostream>#include<cstdio>#include<queue>#include<algorithm>#include<cstring>#include<cmath>#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)#define Set(aa,bb) memset(aa,bb,sizeof(aa))using namespace std;const int maxn=1010,maxm=100010,inf=0x3f3f3f3f;int n,m,s,t;int st[maxm],be[maxm],to[maxm],w[maxm],ne[maxm],flow[maxm],e;int edge[maxm],dis[maxn];bool vis[maxn];void add(int x,int y,int z,int f){    st[++e]=x,to[e]=y,ne[e]=be[x],be[x]=e,w[e]=z,flow[e]=f;    st[++e]=y,to[e]=x,ne[e]=be[y],be[y]=e,w[e]=-z,flow[e]=0;}void spfa(){    Set(dis,inf),Set(vis,0),Set(edge,-1);    queue<int>q;    dis[s]=0;    q.push(s);    while(!q.empty()){        int k=q.front();q.pop(),vis[k]=0;        for(int i=be[k];i!=-1;i=ne[i]){            int u=to[i];            if(flow[i] && dis[u]>dis[k]+w[i]){                dis[u]=dis[k]+w[i];                edge[u]=i;                if(!vis[u]){                    vis[u]=1;                    q.push(u);                }            }        }    }}void bfs(){    int ans=0;    while(1){        spfa();        if(edge[t]==-1) break;        int mine=edge[t];        while(mine!=-1){            --flow[mine];            ++flow[mine^1];            mine=edge[st[mine]];        }        ans+=dis[t];    }    printf("%d\n",ans);}void work(){    Set(be,-1);    e=-1;    scanf("%d%d",&n,&m);    For(i,1,m){        int x,y,z;        scanf("%d%d%d",&x,&y,&z);        add(x,y,z,1);        add(y,x,z,1);    }    s=0,t=n+1;    add(s,1,0,2),add(n,t,0,2);    bfs();}int main(){#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);    freopen("out.txt","w",stdout);#endif    work();    return 0;}
0 0
原创粉丝点击