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

    可以计算负权边的dijkstra

    //最小费用流Dijkstra算法
    
    //Dijkstra算法求最小费用流核心代码:
    
    //h[MAX_V]:导入势保证所有边均为非负边 O(FElogV)
    int min_cost_flow(int n, int v, int s, int t, int f)
    {
    
       int i, ans = 0;
    
       fill(h, h + v, 0);
    
       while(f > 0)    
       {
        //Dijkstra算法:寻找最短路 O(ElogV)
          priority_queue<P, vector<P>, greater<P> > que;
          fill(dis, dis + v, INF);
          dis[0] = 0;
          que.push(P(0, s));
          while(!que.empty())
          {
             P p = que.top();
             que.pop();
    
             int v = p.second;
             if(dis[v] < p.first)
              continue;
             int size = G[v].size();
    
             for(i = 0; i < size; ++i)
             {
                edge es = G[v][i];//****
                if(es.cap > 0 && dis[es.to] > dis[v] + es.cost + h[v] - h[es.to])
    
                {   
    
                   dis[es.to] = dis[v] + es.cost + h[v] - h[es.to]; 
    
                prevv[es.to] = v;
                   preve[es.to] = i;
                   que.push(P(dis[es.to], es.to));
                }
           }
        }
    
        if(dis[t] == INF)
        return -1;
      //更新势
        for(i = 0; i < v; ++i)
         h[i] += dis[i]; 
        int d = f;
        for(i = t; i != s; i = prevv[i])
         d = min(d, G[prevv[i]][preve[i]].cap);
        ans += d * h[t];
    
        f -= d;  
    
        for(i = t; i != s; i = prevv[i])
        {
           edge &es =  G[prevv[i]][preve[i]];
           es.cap -= d;
           G[i][es.rev].cap += d;
        }
      }
    
       return ans;
    }
    View Code

    简单易行但是复杂度不稳定的spfa

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    
    const int INF=0x7f7f7f7f;
    const int MAXN=100000;
    
    struct Edge
    {
        int u,v,w,c,next;//u起点,v终点,w容量,c花费,next下一条边
    }E[MAXN];
    int node,head[MAXN];
    int pre[MAXN],cost[MAXN],vis[MAXN];
    int s,t;
    int n,m,ans1,ans2;
    
    void insert(int u,int v,int w,int c)
    {
        E[++node]=(Edge){u,v,w,c,head[u]};
        head[u]=node;
        E[++node]=(Edge){v,u,0,-c,head[v]};
        head[v]=node;
    }
    
    bool spfa()
    {
        queue<int> Q;
        memset(cost,0x7f,sizeof(cost));
        Q.push(s);
        cost[s]=0;vis[s]=1;
        while(!Q.empty())
        {
            int q=Q.front();Q.pop();
            for(int i=head[q];i;i=E[i].next)
                if(E[i].w&&cost[q]+E[i].c<cost[E[i].v])
                {
                    cost[E[i].v]=cost[q]+E[i].c;
                    pre[E[i].v]=i;
                    if(!vis[E[i].v])
                    {
                        Q.push(E[i].v);
                        vis[E[i].v]=1;
                    }
                }
            vis[q]=0;
        }
        return cost[t]!=INF;
    }
    
    void mcf()
    {
        int minn=INF;
        for(int i=pre[t];i;i=pre[E[i].u])
            minn=min(minn,E[i].w);
        for(int i=pre[t];i;i=pre[E[i].u])
        {
            ans2+=minn*E[i].c;
            E[i].w-=minn;
            E[i^1].w+=minn;
        }
        ans1+=minn;
    }
    
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=m;i++)
        {
            int u,v,w,c;
            scanf("%d%d%d%d",&u,&v,&w,&c);
            insert(u,v,w,c);
        }
        while(spfa()) mcf();
        printf("%d %d",ans1,ans2);//ans1最大流 ans2最小费用
        return 0;
    }
    View Code
  • 相关阅读:
    CodeForcesGym 100524A Astronomy Problem
    ZOJ 2567 Trade
    HDU 3157 Crazy Circuits
    CodeForcesGym 100212E Long Dominoes
    UVALive 6507 Passwords
    [转]
    java socket
    Spark RDD Operations(2)
    Spark cache 和 persist
    vim 基础命令
  • 原文地址:https://www.cnblogs.com/youchandaisuki/p/9890885.html
Copyright © 2011-2022 走看看