zoukankan      html  css  js  c++  java
  • 最小费用最大流模板理解

    //最小费用最大流算法 
    struct Edge
    {
       int from,to,cap,flow,cost;
       Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){}
    };
    
    struct MCMF{
        int n,m;
        vector<Edge> edges;
        vector<int> G[maxn];
        int inq[maxn];//用以判定每个点是否在队列中 
        int d[maxn];//保存源点到每个点的最小费用
        int p[maxn];//每个结点的入弧;
        int a[maxn];//源点到每个结点的最小残量 
        
        void init(int n)
        {
            this->n=n;
            for(int i=0;i<n;i++)
            G[i].clear();
            edges.clear;
         } 
    };
    
    void AddEdge(int from,int to,int cap,int cost)
    {
        edges.push_back(Edge(from,to,cap,0,cost));
        edges.push_back(Edge(to,from,0,0,-cost));
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    //其实感觉这个算法是求最大流和求最短路径算法的结合,把费用看作是路径 
    bool BellmanFord(int s,int t,int& flow,long long& cost) //由于费用可能是负值,所以用BellmanFord算法 
    {
        for(int i=0;i<n;i++)
        d[i]=inf;   //初始化,把到每个点的最小费用设为inf,无穷大
        memset(inq,0,sizeof(inq));
        d[s]=0,inq[s]=1,p[s]=0,a[s]=inf;//初始化
        
        queue<int> Q;
        Q.push(s);
        while(!Q.empty())
        {
            int u=Q.front();Q.pop();
            que[u]=0;   //只要退出队列,则此结点可再次被访问,若发现有比的当前d[u]更小的d[fa[u]]+w[fa[u]][u] 
            for(int i=0;i<G[i].size();i++)      //则更新d[u],并且用其更新它的其余子结点 
          {
              Edge& e=edges[G[u][i]];
              if(e.cap>e.flow&&d[e.to]>d[u]+e.cost)//最大流与最短路径更新条件的结合 
              {
                  d[e.to]=d[u]+e.cost;
                  p[e.to]=G[u][i];
                  a[e.to]=min(a[u],e.cap-e.flow);
                  if(!inq[e.to]){Q.push(e.to);inq[e.to]=1;}
               }
          }
        }
        if(d[t]==inf)  return false; //则证明已经无法更新到汇点t,即所有的最小费用最大流路径已经被找完 
        flow+=a[t];
        cost+=(long long)d[t]*(long long)a[t];
        for(int u=t;u!=s;u=edges[p[u]].from)
        {
            edges[p[u]].flow+=a[t];  //残量网络一条增广路中所有正向边+flow 
            edges[p[u]^1].flow-=a[t];//所有反向边-flow 
        }                            //构成一条新的残量网络 
        return true;
    }
    //但是上述算法并没有判定网络当中有没有形成负圈,所以要保证网络当中没有负圈 
    
    int MincostMaxflow(int s,int t,long long& cost)
    {
        int flow=0;cost=0;
        while(BellmanFord(s,t,flow,cost));
        return flow;
     } //emmmmm,新生题解还没写,去写题解了。
  • 相关阅读:
    xcode6创建工程时 默认去掉了PrefixHeader.pch
    KVC访问私有成员
    Apple Watch 中Context Menu的应用
    Apple Watch应用创建
    NSURLConnection加载数据并展示
    UIView 的exclusiveTouch clipsToBounds和transform属性
    Shell的一些基本用法
    NS_ENUM和NS_OPTIONS
    iOS国际化时遇到错误: the data couldn't be read because it isn't in the correct format.
    iOS8中UIAlertController的使用
  • 原文地址:https://www.cnblogs.com/rainyskywx/p/9985608.html
Copyright © 2011-2022 走看看