• 最小费用最大流


    最大流最小费用:链式前向星 + add_edg()+ SPFA() + MCMF()

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #define INF 0x3f3f3f3f
    #define MAX 5005
    #define MAX_EDG 50005
    
    using namespace std;
    
    typedef struct Node{
        int to;        //边的终点 
        int cap;    //当前最大容量 
        int cost;    //单位流量的费用 
        int next;    //相同起点的下一条边在map中的编号(位置) 
    }Node;
    
    Node map[MAX_EDG*2];    //存边:正向边 + 反向边 
    int vis[MAX];
    int dis[MAX];        //s到第i个顶点的最小代价 
    int pre[MAX];
    int flow[MAX];        //s到第i个顶点可更新的最大流量 
    int head[MAX];        //第i个顶点的第一条边在map中的位置 
    int count;        //计数,第几个顶点 
    int n,m,s,t;        
    int max_flow, min_cost;        //最大流 最小费用 
    queue<int> q;
    
    void add_edge(int from, int to, int cap, int cost){        //from起点    to终点    cap当前容量     cost单位费用 
        map[count].to=to;
        map[count].cap=cap;
        map[count].cost=cost;
        map[count].next=head[from];
        head[from]=count++;            //更新count        
    }
    
    bool spfa(int s, int t){
        memset(dis,INF,sizeof(dis));
        memset(vis,0,sizeof(vis));
        q.push(s);
        vis[s]=1;
        dis[s]=0;
        flow[s]=INF;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;        //为什么
            for(int i=head[u] ;i!=-1; i=map[i].next){        //i是边在map中的编号 
                if(!map[i].cap)        continue;        //当前边没有可增加的容量了,就跳过
                int v=map[i].to;
                int w=map[i].cost;
                if(dis[v] > dis[u] + w)
                {
                    dis[v]=dis[u]+w;
                    flow[v]=min(flow[u],map[i].cap);    //取到边的起点u可更新的流量和这条边的剩余容量的最小值
                    pre[v]=i;        //
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    } 
                } 
            } 
        }
        return dis[t]!=INF;        //
    }
    
    
    void MFMC(int s, int t){        //
        while(spfa(s,t)){        //还存在增广路 
            int x= t;
            max_flow+=flow[t];
            min_cost+=flow[t]*dis[t];
            while(x!=s){                //遍历增广路 
                int i=pre[x];
                map[i].cap-=flow[t];        //正向弧减 
                map[i^1].cap+=flow[t];        //反向弧加 
                x=map[i^1].to;
            }
        }
    }
    
    int main(){
        int u,v,cap,cost;
        while(scanf("%d %d %d %d",&n,&m,&s,&t)!=EOF){
            memset(head,-1,sizeof(head));
            count=0;
            max_flow=min_cost=0;
            for(int i=0;i<m;i++){
                scanf("%d %d %d %d",&u,&v,&cap,&cost);
                add_edge(u,v,cap,cost);        //正向边 
                add_edge(v,u,0,-cost);        //反向边的容量为0,费用为-cost 
            }
            MFMC(s,t);
            printf("%d %d
    ",max_flow,min_cost);
        }
        return 0;
    }
  • 相关阅读:
    C 标准库
    C 标准库
    C 标准库
    C 标准库
    Chrome内核保存为mhtml(单网页)
    C 标准库
    C 标准库
    【转】AOP
    [转]控制反转与依赖注入模式
    [转]乐观锁、悲观锁、死锁的区别
  • 原文地址:https://www.cnblogs.com/shiliuxinya/p/12201756.html
Copyright © 2020-2023  润新知