优化BFS的实现

时间:2015-12-04 17:09:49

标签: c++ algorithm graph breadth-first-search

我正在学习Graph的基础知识并从中解决问题 https://www.hackerrank.com/challenges/bfsshortreach。代码工作正常,但我得到一个测试用例的TLE。我将cin / cout改为printf / scanf,希望能让它被接受,但没有成功。我现在的代码是

#include <iostream>
#include <queue>
#include <climits>
#include <stdio.h>
#include <queue>
#include <list>
#include <vector>

struct Graph
{
    int size;
    std::list<int> *adj;
};

Graph* createGraph(int size)
{
    Graph *graph = new Graph();
    graph->size = size;
    graph->adj = new std::list<int>[size];
    return graph;
}
void addEdge(Graph *graph, int source, int dest)
{
    graph->adj[source].push_back(dest);
    graph->adj[dest].push_back(source);
}

void printGraph(Graph *graph)
{
    for (int i = 0; i < graph->size; ++i)
    {
        for(std::list<int>::iterator it = graph->adj[i].begin(); it!= graph->adj[i].end(); ++it)
          {
            std::cout<<*it<<' ';
          }
          std::cout<<std::endl;
    }
}

void BFS(Graph *graph, int src)
{
    std::queue <int> nodes;
    std::vector<bool> v(graph->size,false);
    std::vector<int> distance(graph->size, INT_MAX);
    v[src] = true;
    distance[src] = 0;
    nodes.push(src);
    std::list<int>::iterator it;
    while(!nodes.empty())
    {
        int temp = nodes.front();
        v[temp] = true;
        nodes.pop();
        for(it = graph->adj[temp].begin(); it!= graph->adj[temp].end(); ++it)
          {
            if(!v[*it])
            {
                nodes.push(*it);
                int current = distance[temp] != INT_MAX? distance[temp] : 0;
                distance[*it] = std::min(current + 6, distance[*it]);
            }
          }
    }
    for (int i = 0; i < distance.size(); ++i)
    {
        int dist = distance[i] != INT_MAX ?  distance[i] : -1;
        if(i!= src)
        {
            printf("%d ", dist);
        }
    }
        printf("\n");
}

int main(int argc, char const *argv[])
{
    int T;
    scanf(" %d", &T);
    while(T--) {
        int n, m, s;
        // cin>>n>>m;m
        scanf(" %d %d", &n, &m);
        Graph *graph = createGraph(n);
        while(m--)
        {
            int x, y;
            // cin>>x>>y;
            scanf(" %d %d", &x, &y);
            addEdge(graph, x-1, y-1);
        }
        // cin>>s;
        scanf(" %d", &s);
        BFS(graph, s-1);
        // printGraph(graph);
    }
    return 0;
}

我相信这个算法O(m log n) 的时间复杂度。插入边缘所需的时间复杂度为 O(1) 。所以AFAIK,这是我们能做的最好的(也许?)。我不确定这是否是存储图表的最佳方式。任何更好,更快的方法来存储图表和建议来​​改善这一点都会很棒。

1 个答案:

答案 0 :(得分:0)

这不是优化问题。在将它们放入rcMask之后,您应该将您放入队列true中的每个节点的访问权限设置为访问,否则您将在很长一段时间内重新访问某些节点。您将queue放入队列但未将其访问权限设置为node并将其延迟,直到您将该节点从队列中取出,然后将其访问权限设置为true。那会发生什么?请考虑此图表trueV={a,b,c,d}。首先E={a->b, a->c, a->d, b->d, c->d}a推入队列但未设置其访问者。然后b,c,db推送到队列,之后d也将c推送到队列。所以你的队列看起来像d。所以你要三次访问q={d,d,d}。这是一个非常小的案例,你可以看到大案例,这怎么会导致一个大问题。

这样的事情:

d