最大流最小费用

最大流最小费用:链式前向星 + add_edg()+ 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\n",max_flow,min_cost);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/shiliuxinya/p/12201756.html