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