最小费用最大流问题,MCMF模板
// 最小费用最大流 struct MCMF { struct node { int vi,id,wi,ci; }; const int inf = 0x3f3f3f3f; int S,T,mxflow,cost; std::vector<int> dis,to,cur; std::vector<bool> vis; std::vector<std::vector<node>> r; MCMF(int n,int s,int t) : dis(n + 10),vis(n + 10),r(n + 10),cur(n + 10),S(s),T(t),mxflow(0),cost(0){} int spfa()//spfa代替bfs寻找增广路 { std::fill(dis.begin(), dis.end(), inf); std::fill(vis.begin(), vis.end(), 0); queue<int> q; q.push(S);dis[S] = 0; while(q.size()) { int x = q.front();q.pop(); vis[x] = 0;//vis用于判断节点是否在队列中,若在,则最短路更新时不需重复加入队列 for(auto tmp:r[x]) { if(tmp.wi && dis[x] + tmp.ci < dis[tmp.vi]) { dis[tmp.vi] = dis[x] + tmp.ci; if(!vis[tmp.vi]) q.push(tmp.vi),vis[tmp.vi] = 1; } } } if(dis[T] == inf) return 0; return 1; } int dfs(int x,int fl) { if(x == T) return fl; vis[x] = 1;//此处vis用于判断节点是否在目前选择的增广路上,若在,则不能重复加入。因为例题路径可能有0环存在 int rem = fl; for(int i = 0;i < r[x].size();i ++) { if(rem == 0) break; int vi = r[x][i].vi,wi = r[x][i].wi,ci = r[x][i].ci; if(dis[x] + ci == dis[vi] && wi && !vis[vi]) { int flow = dfs(vi,min(rem,wi));//找到可行流 if(flow > 0) { rem -= flow; r[x][i].wi -= flow; r[vi][r[x][i].id].wi += flow; cost += ci*flow;//计算费用 if(rem <= 0) break; } } } vis[x] = 0;//撤销点,看看能不能继续找到一条增广路 if(fl == rem) dis[x] = inf;//如果从x点出发找不到可行流,则不再找x这个点 return fl - rem; } void addEdge(int u,int v,int w,int c)//vector存图 { r[u].push_back({v,(int)r[v].size(),w,c}); r[v].push_back({u,(int)r[u].size() - 1,0,-c}); } void Mxflow()//费用流 { while(spfa()) { for(auto &v:cur) v = 0; mxflow += dfs(S,inf); } //printf("%d %d\n",mxflow,cost); } };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现