边们增加了费用 求费用最少的最大流
在残余网络中,用spfa跑费用的最短路,然后沿着这条花费最少的增广路进行增广
(表示怀疑这样做的时间复杂度会比较高 因为他甚至都没有沿着分层图上最短路去增广...不过貌似没有别的办法...)
看起来很容易出现负圈并且死循环的样子 负圈的问题感觉大佬解释得比较清楚:
在费用最短路增广的过程中产生的剩余网络不可能存在负圈,原因是最短增广路增广能够保证每次迭代的结果是当前流下的费用
最小的解。因此如果存在负圈的话消去这个负圈就能达到一个更小的费用,这和前面那个性质矛盾。至于那个性质的证明是对流量
进行归纳来完成的。
大概就是不含初始负圈的话不会产生负圈吧...
(链接:http://bbs.youkuaiyun.com/topics/300017499?fps=1&locationNum=10)
void addedge(int u, int v, int w, int cost){ edge[tot] = Edge(u, v, w, 0, cost, head[u]); head[u] = tot++; edge[tot] = Edge(v, u, 0, 0, -cost, head[v]); head[v] = tot++; } bool spfa(int st, int ed){ queue<int>Q; memset(pre, -1, sizeof pre); memset(inq, 0, sizeof inq); memset(d, inf, sizeof d); inq[st] = 1; d[st] = 0; Q.push(st); while(!Q.empty()){ int u = Q.front(); Q.pop(); inq[u] = 0; for(int i = head[u]; ~i; i = edge[i].nxt){ int v = edge[i].v, cost = edge[i].cost; if(d[v] > d[u]+cost && edge[i].w-edge[i].f){ d[v] = d[u]+cost; pre[v] = i; if(!inq[v]){ inq[v] = 1; Q.push(v); } } } } return pre[ed] != -1; } int MCMF(int st, int ed){ int flow = 0; ans = 0; while(spfa(st, ed)){ int MIN = inf; for(int i = pre[ed]; ~i; i = pre[edge[i^1].v]){ if(MIN > edge[i].w-edge[i].f) MIN = edge[i].w-edge[i].f; } for(int i = pre[ed]; ~i; i = pre[edge[i^1].v]){ edge[i].f += MIN; edge[i^1].f -= MIN; } ans += d[ed]*MIN; flow += MIN; } return flow;