图论 —— 网络流 —— 费用流 —— MCMF 算法
【概述】
EK 算法是每次用广搜寻找一条最短的增广路,然后沿其增广,而 MCMF 算法是在 EK 算法的基础上,每次用 SPFA 计算图的距离标号,然后沿着可行边进行增广,即将 EK 算法中的 bfs 替换为 SPFA 求最短路,边权为该边的单位流量花费,即改变遍历的优先级来实现。
【基本思想】
1.每次查找是否存在从源点到汇点可增广的路径(源点到汇点的最短路且路径上的所有边均不能满流),并用 pre[i] 记录路径上到达点 i 的边的编号。
2.若存在这样的路径,则从汇点沿着 pre 数组向前找,找到该路径上可以增广的流量 Min(所有边中剩余流量最小的),再从汇点遍历一次,正向边增加流量 Min,反向边减少 Min,总费用累加 Min * edge[i].cost,总流量累加 Min
【实现】
struct Edge{
int from,to;
int cap,flow;
int cost;//费用
int next;//指向下一条边的编号
}edge[N];
int head[N],tot;
int dis[N];//单源最短路径
bool vis[N];//SPFA中用于判断是否在队列
int pre[N];//记录从S到i的最小费用路径上的最后一条弧编号
void addEdge(int x,int y,int cap,int cost){
edge[tot].from=x;
edge[tot].to=y;
edge[tot].cap=cap;
edge[tot].flow=0;
edge[tot].cost=cost;
edge[tot].next=head[x];
head[x]=tot++;
edge[tot].from=y;
edge[tot].to=x;
edge[tot].cap=0;
edge[tot].flow=0;
edge[tot].cost=-cost;
edge[tot].next=head[y];
head[y]=tot++;
}
bool SPFA(int S,int T) {
queue<int> Q;
memset(dis,INF,sizeof(dis));
memset(vis,false,sizeof(vis));
memset(pre,-1,sizeof(pre));
dis[S]=0;
Q.push(S);
while(!Q.empty()) {
int x=Q.front();
Q.pop();
vis[x]=false;
for(int i=head[x];i!=-1;i=edge[i].next) {
int y=edge[i].to;
int cost=edge[i].cost;
int cap=edge[i].cap;
int flow=edge[i].flow;
if(dis[y]>dis[x]+cost&&cap>flow) {
dis[y]=dis[x]+cost;
pre[y]=i;
if(!vis[y]){
vis[y]=true;
Q.push(y);
}
}
}
}
return pre[T]!=-1;
}
void MCMF(int S,int T,int &flow,int &cost){
while(SPFA(S,T)){//每次寻找花销最小的路径
int minn=INF;
for(int i=pre[T];i!=-1;i=pre[edge[i^1].to])//寻找最小增广流
minn=min(minn,edge[i].cap-edge[i].flow);
for(int i=pre[T];i!=-1;i=pre[edge[i^1].to]) {
edge[i].flow+=minn;
edge[i^1].flow-=minn;
cost+=edge[i].cost*minn;//增广流的花销
}
flow+=minn;//总流量增加
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
tot=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++){
int x,y,cap,cost;
scanf("%d%d%d%d",&x,&y,&cap,&cost);
addEdge(x,y,cap,cost);//正向边
}
int cost=0,flow=0;//最小费用、最大流
int S=1,T=n;//源点与汇点
MCMF(S,T,flow,cost);
printf("minCost:%d\n",cost);
printf("maxFlow:%d\n",flow);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App