网络流学习笔记(2)

来源:互联网 发布:专业音频测试软件 编辑:程序博客网 时间:2024/06/05 14:15

最小费用最大流:在保证最大流的前提下,让费用最小。
我们有两种思路:
1.先保证流最大,再去找费用最小的。
2.保证费用最小,去找最大流。
通常情况下我们会选择第二种。我们想一下最大流是怎么做的,bfs分层图然后dfs每次只找深度+1的去增广。
如果我们要保证最小费用呢?每次去找费用最小的增广。
我们可以SPFA先处理出最小费用以及到那个节点的边。(pre)。
增广时按这些边去处理残量和费用。

#include<bits/stdc++.h>using namespace std;#define ll long long#define mp make_pairtypedef pair<int,int>par;const int INF=1e8+5;const int MAXN=8e4+5;int n,m,s,t;struct edge{    int to,next,w,cost,u;}e[MAXN<<1];int head[MAXN],cnt=1;inline void add(int u,int v,int w,int c){e[++cnt]=(edge){v,head[u],w,c,u},head[u]=cnt;}int dis[MAXN],pre[MAXN];bool vis[MAXN];queue<int>q;bool spfa(int x){    memset(pre,0,sizeof(pre));    memset(vis,0,sizeof(vis));    for(int i=1;i<=n;i++)dis[i]=INF;    q.push(x);dis[x]=0;vis[x]=1;    while(q.size()){        int u=q.front();q.pop();vis[u]=0;        for(int i=head[u];i;i=e[i].next){            int v=e[i].to,w=e[i].cost;            if(e[i].w){                if(dis[u]+w<dis[v]){                    dis[v]=dis[u]+w;pre[v]=i;                    if(!vis[v]){                        vis[v]=1;q.push(v);                    }                }            }        }    }    if(dis[t]==INF)return 0;    return 1;}par MCMF(){    int ans=0,flow=0,tem;    while(spfa(s)){        tem=INF;        for(int i=pre[t];i;i=pre[e[i].u]){            tem=min(tem,e[i].w);        }        for(int i=pre[t];i;i=pre[e[i].u]){            e[i].w-=tem;            e[i^1].w+=tem;            ans+=tem*e[i].cost;        }        flow+=tem;    }    return mp(flow,ans);}int main(){    int tem1,tem2,tem3,tem4;    scanf("%d%d%d%d",&n,&m,&s,&t);    for(int i=1;i<=m;i++){        scanf("%d%d%d%d",&tem1,&tem2,&tem3,&tem4);        add(tem1,tem2,tem3,tem4);        add(tem2,tem1,0,-tem4);    }    par ans=MCMF();    printf("%d %d\n",ans.first,ans.second);    return 0;}
原创粉丝点击