// 最小费用最大流 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); } };
标签:tmp,MCMF,int,vi,最小,wi,vis,模板,dis From: https://www.cnblogs.com/chayi/p/17604353.html