使用hashmap而不是邻接矩阵实现maxflow算法

时间:2015-07-19 08:48:48

标签: c++ algorithm hashmap

我试图通过使用散列图来表示图形而不是邻接矩阵来节省一些空间,我使用邻接矩阵运行相同的片段,一切正常,但是只要我将数据结构更改为hashmap,它在无限循环中遇到,无限循环是因为定义了bsf函数返回boolean值,更具体地说,错误是在行中:if ((!visited[v]) && (rGraph[make_pair(u, v)] > 0))不知怎的,如果条件不是我将rGraph表示为散列图时工作正常。

我还想知道使用散列图来表示图表是一种首选方式吗?

以下是附加代码:

bool bfs(map<pair<int, int>, int> rGraph, int s, int t, int parent[])
{

    // Create a visited array and mark all vertices as not visited
    bool visited[V];
    memset(visited, 0, sizeof(visited));

    // Create a queue, enqueue source vertex and mark source vertex
    // as visited
    queue <int> q;
    q.push(s);
    visited[s] = true;
    parent[s] = -1;

    // Standard BFS Loop
    while (!q.empty())
    {
        int u = q.front();
        q.pop();

        for (int v=0; v<V; v++)
        {
            cout << "Value of graph at: " <<u << "  , " << v << " : " << rGraph[make_pair(u, v)] << "\n";
            //cout << "!visited[v] : " << (!visited[v]) << "rGraph[u][v] : " << rGraph[make_pair(u, v)] << "\n";
            cout << "if condition :  " << ((!visited[v]) && (rGraph[make_pair(u, v)] > 0)) << "\n";
            if ((!visited[v]) && (rGraph[make_pair(u, v)] > 0))
            {
                q.push(v);
                parent[v] = u;
                visited[v] = true;
            }
        }
    }

    // If we reached sink in BFS starting from source, then return
    // true, else false
    return (visited[t] == true);
}

// Returns tne maximum flow from s to t in the given graph
int fordFulkerson(map<pair<int, int> , int> graph , int s, int t)
{
    int u, v;

    // Create a residual graph and fill the residual graph with
    // given capacities in the original graph as residual capacities
    // in residual graph
    map<pair<int, int>, int>rGraph; // Residual graph where rGraph[i][j] indicates
    // residual capacity of edge from i to j (if there
    // is an edge. If rGraph[i][j] is 0, then there is not)
    for (u = 0; u < V; u++){
        for (v = 0; v < V; v++){
            rGraph[make_pair(u, v)] = graph[make_pair(u, v)];
        }
    }

    int parent[V];  // This array is filled by BFS and to store path

    int max_flow = 0;  // There is no flow initially

    // Augment the flow while tere is path from source to sink
    while (bfs(rGraph, s, t, parent))
    {
        // Find minimum residual capacity of the edhes along the
        // path filled by BFS. Or we can say find the maximum flow
        // through the path found.
        int path_flow = INT_MAX;
        for (v=t; v!=s; v=parent[v])
        {
            u = parent[v];
            path_flow = min(path_flow, int(rGraph[make_pair(u, v)]));
        }

        // update residual capacities of the edges and reverse edges
        // along the path
        for (v=t; v != s; v=parent[v])
        {
            u = parent[v];
            rGraph[make_pair(u, v)] -= path_flow;
            rGraph[make_pair(u, v)] += path_flow;
        }

        // Add path flow to overall flow
        max_flow += path_flow;
    }

    // Return the overall flow
    return max_flow;
}

int main(){
    map< pair<int, int>, int > graph;
    graph[make_pair(0, 1)] = 16;
    graph[make_pair(0, 2)] = 13;
    graph[make_pair(1, 2)] = 10;
    graph[make_pair(1, 3)] = 12;
    graph[make_pair(2, 1)] = 4;
    graph[make_pair(2, 4)] = 14;
    graph[make_pair(3, 2)] = 9;
    graph[make_pair(3, 5)] = 20;
    graph[make_pair(4, 3)] = 7;
    graph[make_pair(4, 5)] = 4;*/


    cout << "The maximum possible flow is " << fordFulkerson(graph, 0, 5) << "\n";

return 0;
}

邻接矩阵看起来像:

int graph[V][V] = { {0, 16, 13, 0, 0, 0},
                    {0, 0, 10, 12, 0, 0},
                    {0, 4, 0, 0, 14, 0},
                    {0, 0, 9, 0, 0, 20},
                    {0, 0, 0, 7, 0, 4},
                    {0, 0, 0, 0, 0, 0}};

2 个答案:

答案 0 :(得分:2)

首先,只需查看代码 - 您没有使用hashmap - 您正在使用map(在大多数实现中,请阅读:红黑树)。相当于&#34; hashmap&#34;将是unordered_map。但是,如果你想节省内存 - 你选择了正确的容器unordered_map可能比map消耗更多内存 - unordered_map(hashmap)需要连续区域桶的内存:当然所有桶都不会占用。)

现在出现问题: 执行rGraph[make_pair(u, v)] 后,您可能会在地图中创建新元素。索引操作符返回(参见cppreference):

  • 引用索引make_pair(u, v)
  • 指向的现有元素
  • 如果make_pair(u, v)指向的元素不存在 - 它会在该索引下创建一个新元素,并返回对该新元素的引用

如果要检查map / unordered_map中是否存在元素,则必须使用find方法:

auto p = make_pair(u, v)];
auto iter = rGraph.find(p);
if(iter != rGraph.end())
{//element 'rGraph[p]' exists
}
else
{//element 'rGraph[p]' does not exist
}

您还可以组合(可能)插入新元素并检查新元素是否实际创建 - 这通常比两个单独的insertfind更有效(请参阅cppreference) :

auto p = make_pair(u, v)];
auto res = rGraph.insert(make_pair(p,1)); //insert value '1'
if(res.second)
{//new element was inserted
}
else
{//element already existed
}
//here res.first is an iterator pointing to the element rGraph[p] - newly inserted or not

答案 1 :(得分:1)

您应该使用count或find方法来检查地图中项目的存在,而不是运算符[],因为它构造了一个新项目(如果它不存在)。所以改变

rGraph[make_pair(u, v)]>0

rGraph.count(make_pair(u, v))>0

另外,我可能建议通过引用传递任何大对象(例如地图)。此外,如此处所述,您可以使用&#34; unordered_map&#34;这是一个哈希表,而不是&#34; map&#34;这是一棵树,因为你不需要订购地图。

相关问题