zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      学习了网络流最基本的最大流算法以后,当然就会有更进一步的问题,那就是最小费用最大流。

      顾名思义,最小费用最大流就是在原本的有向图中,单位流量加入费用,并在原本最大流的基础上找到一个费用最小的最大流。

      很明显,在一个网络中最大流可能有多种流法(懂那个意思就行了,听着别扭就算了啊,不要紧的纠结要不要得?),所以在原本最大流的基础上,运用Spfa或者其他方法进行类似最短路的算法就可以找到最小费用最大流,,,具体还是看代码吧(我实在是太懒了_(:з」∠)_):

      这里是洛谷的模板题

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #define inf 1e9
    using namespace std;
    const int N=5050;
    const int M=50050;
    deque<int>Q;
    int n,m,start,endd;
    int dis[N],ans,res;
    int head[N],size=1;
    bool vis[N],inq[N];
    struct Node{
      int to,val,cost,next;
    }edge[M<<1];
    inline int read()
    {
      char ch=getchar();int num=0;bool flag=false;
      while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
      while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
      return flag?-num:num;
    }
    inline void add(int x,int y,int z,int c)
    {
      edge[++size].to=y;
      edge[size].val=z;
      edge[size].cost=c;
      edge[size].next=head[x];
      head[x]=size;
    }
    inline void add_edge(int x,int y,int z,int c)
    {add(x,y,z,c);add(y,x,0,-c);}
    void ready()
    {
      memset(head,-1,sizeof(head));
      n=read();m=read();
      start=read();endd=read();
      for(int i=1;i<=m;i++){
        int x=read();int y=read();
        int z=read();int c=read();
        add_edge(x,y,z,c);
      }
    }
    inline bool bfs()
    {
      for(int i=0;i<=n;i++)dis[i]=inf;
      memset(inq,false,sizeof(inq));
      dis[endd]=0;inq[endd]=true;
      Q.push_back(endd);
      while(!Q.empty()){
        int x=Q.front();Q.pop_front();
        inq[x]=false;
        for(int i=head[x];i!=-1;i=edge[i].next){
          int y=edge[i].to;
          if(edge[i^1].val&&dis[y]>dis[x]-edge[i].cost){
        dis[y]=dis[x]-edge[i].cost;
        if(!inq[y]){inq[y]=true;
          if(Q.empty()||dis[y]>=dis[Q.front()])Q.push_back(y);
          else Q.push_front(y);
        }
          }
        }
      }
      return dis[start]<dis[0];
    }
    inline int dfs(int u,int flow)
    {
      vis[u]=true;
      if(u==endd||flow==0)return flow;
      int used=0;
      for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(!vis[v]&&edge[i].val&&dis[v]==dis[u]-edge[i].cost){
          int ka=flow-used;
          ka=dfs(v,min(edge[i].val,ka));
          edge[i].val-=ka;
          edge[i^1].val+=ka;
          used+=ka;
          if(used==flow)return used;
        }
      }
      return used;
    }
    void work()
    {
      while(bfs()){
        vis[endd]=true;
        while(vis[endd]){
          memset(vis,false,sizeof(vis));
          int flow=dfs(start,inf);
          res+=flow*dis[start];
          ans+=flow;
        }
      }
      printf("%d %d",ans,res);
    }
    int main()
    {
      ready();
      work();
      return 0;
    }

     这里BFS的时候使用了双端队列,实际上不用也可以,但是用的话会快不少,据我实测,使用双端队列最慢的点388ms,不用双端队列最慢的点600ms

    差距貌似挺大的。。。囧。。。不过一般情况下不用也是没问题的(除非出题人丧心病狂到卡这种数据。。。)

  • 相关阅读:
    [Leetcode]279.完全平方数
    map处理数组 替换item的值
    Immutable数据详解 merge方法及其原理解释
    dev-server的mock配置
    react 国际化 react-i18next
    import * as xxx from 'xxx'
    http-server测试本地打包程序是否有问题
    git 操作
    react hook 官方文档阅读笔记
    吐槽下百度搜索引擎的权重问题
  • 原文地址:https://www.cnblogs.com/cytus/p/8099125.html
Copyright © 2011-2022 走看看