我不知道这个MCMF代码有什么问题

时间:2017-11-26 01:44:56

标签: c++

我正在研究MCMF(最低成本 - 最大流量)算法。

我完成了对MCMF代码的编码,但它仍然会出现运行时错误。

我无法找到原因。

我尽力找到它发生的原因,但我找不到解决方案。

我认为我的输入数据没有问题。

这是我的代码。

struct MCMF{
    struct edge{
        int to, cap, cost, rev;
    };
    int size, src, sink;
    vector<vector<edge> > G;
    vector<int> dist, par, edgeIdx;
    MCMF(int size, int src, int sink){
        G = vector<vector<edge> >(size);
        par = vector<int>(size);
        edgeIdx = vector<int>(size);
        this->size = size;
        this->src = src;
        this->sink = sink;
    }
    bool spfa(){
        dist = vector<int>(size, inf);
        vector<bool> inQ = vector<bool>(size, false);
        queue<int> q;
        q.push(src);
        inQ[src] = true;
        dist[src] = 0;
        while(!q.empty()){
            int here = q.front();
            q.pop();
            inQ[here] = false;
            for(int i = 0 ; i < (int)G[here].size(); i++){
                auto e = G[here][i];
                if(e.cap > 0 && dist[here] + e.cost < dist[e.to]) {
                    dist[e.to] = dist[here] + e.cost;
                    par[e.to] = here;
                    edgeIdx[e.to] = i;
                    if(!inQ[e.to]) q.push(e.to), inQ[e.to] = true;
                }
            }
        }
        return dist[sink] != inf;
    }
    pair<int,int> getMCMF(){
        int maxFlow = 0;
        int minCost = 0;
        while(1){
            if(!spfa()) break;
            int minFlow = inf;
            int costSum = 0;
            for(int p = sink; p != par[p]; p = par[p]){
                auto& e = G[par[p]][edgeIdx[p]];
                minFlow = min(minFlow, e.cap);
                costSum += e.cost;
            }
            for(int p = sink; p != par[p]; p = par[p]){
                auto& e = G[par[p]][edgeIdx[p]];
                e.cap -= minFlow;
                G[e.to][e.rev].cap += minFlow;
            }
            maxFlow += minFlow;
            minCost += costSum * minFlow;
        }
        return {maxFlow, minCost};
    }
    void addEdge(int from, int to, int cap, int cost){
        G[from].push_back({to, cap, cost, (int)G[to].size()});
        G[to].push_back({from, 0, -cost, (int)G[from].size()-1});
    }
};

1 个答案:

答案 0 :(得分:1)

我认为你应该添加代码

par[src] = src

如果您不想更改

for(int p = sink; p != par[p]; p = par[p])

我认为如果你改变

会更好
p != par[p] 

p != src
在你的for循环中

因为理解代码更清楚,你不必添加'par [src] = src'

如果您更正我所说的部分

,这是完整的代码
struct MCMF{
    struct edge{
        int to, cap, cost, rev;
    };
    int size, src, sink;
    vector<vector<edge> > G;
    vector<int> dist, par, edgeIdx;
    MCMF(int size, int src, int sink){
        G = vector<vector<edge> >(size);
        par = vector<int>(size);
        edgeIdx = vector<int>(size);
        this->size = size;
        this->src = src;
        this->sink = sink;
    }
    bool spfa(){
        dist = vector<int>(size, inf);
        vector<bool> inQ = vector<bool>(size, false);
        queue<int> q;
        q.push(src);
        inQ[src] = true;
        dist[src] = 0;
        while(!q.empty()){
            int here = q.front();
            q.pop();
            inQ[here] = false;
            for(int i = 0 ; i < (int)G[here].size(); i++){
                auto e = G[here][i];
                if(e.cap > 0 && dist[here] + e.cost < dist[e.to]) {
                    dist[e.to] = dist[here] + e.cost;
                    par[e.to] = here;
                    edgeIdx[e.to] = i;
                    if(!inQ[e.to]) q.push(e.to), inQ[e.to] = true;
                }
            }
        }
        return dist[sink] != inf;
    }
    pair<int,int> getMCMF(){
        int maxFlow = 0;
        int minCost = 0;
        while(1){
            if(!spfa()) break;
            int minFlow = inf;
            int costSum = 0;
            for(int p = sink; p != src; p = par[p]){
                auto& e = G[par[p]][edgeIdx[p]];
                minFlow = min(minFlow, e.cap);
                costSum += e.cost;
            }
            for(int p = sink; p != src; p = par[p]){
                auto& e = G[par[p]][edgeIdx[p]];
                e.cap -= minFlow;
                G[e.to][e.rev].cap += minFlow;
            }
            maxFlow += minFlow;
            minCost += costSum * minFlow;
        }
        return {maxFlow, minCost};
    }
    void addEdge(int from, int to, int cap, int cost){
        G[from].push_back({to, cap, cost, (int)G[to].size()});
        G[to].push_back({from, 0, -cost, (int)G[from].size()-1});
    }
};