在彩色图表上执行DFS时出现分段错误

时间:2015-02-03 20:17:12

标签: c++ segmentation-fault depth-first-search

这是我的代码:

#include <bits/stdc++.h>

using namespace std;
#define limt 101

//edge stores the edges for each node
//since it is defined outside main, i don't think it is the cause for
//segmentation fault

vector<int> edge[limt][limt];
int vist[limt], tgt;

//dfs call for a node numbered <i>u</i>
//and for only the edges colored <i>c</i>
int dfs(int u, int c)
{
   if (u == tgt) return 1;

   vist[u] = 1;

   for (int i = 0; i < edge[u][c].size(); ++i) {
      if (dfs(edge[u][c][i], c)) return 1;
   }

   vist[u] = 0;
   return 0;
}

int main()
{
   //n : number of nodes
   //m: number of edges
   //c: color of edge
   int n, m;
   int u, v, c;
   cin >> n >> m;
   for (int i = 0; i < m; ++i) {
      cin >> u >> v >> c;
      edge[u][c].push_back(v);
      edge[v][c].push_back(u);
   }
   //q: number of queries/test-cases
   int q, x, y;
   cin >> q;
   while (q--) {
      cin >> x >> y;
      memset(vist, 0, sizeof(vist));
      int ans = 0;
      vist[x] = 1;
      tgt = y;

      //program crashes for second test-case after reaching here

      //i - the color of edge
      //j - all the edges from x of color i
      for (int i = 0; i < limt; ++i) {
         for (int j = 0; j < edge[x][i].size(); ++j) {
             ans += dfs(edge[x][i][j], i);
         }
      }
      vist[x] = 0;
      cout << ans << endl;
   }

   return 0;
}

我给的输入是:

4 5
1 2 1
1 2 2
2 3 1
2 3 3
2 4 3
3
1 2
3 4
1 4

这里 q 是测试用例的数量,第一种情况运行良好并给出输出 2 但在第二种情况下程序崩溃时出现分段错误。我不知道它里面的错误是什么。我确信我没有引起任何溢出,因为声明在 main()之外。

1 个答案:

答案 0 :(得分:2)

在第二种情况下,dfs函数会导致无限递归。

第一个电话是dfs(u=2, c=1);,调用dfs(u=1, c=1);,调用dfs(u=2, c=1);,然后点击广告。

如果在调试器中运行代码,您应该能够通过在分段错误点输出堆栈跟踪来查看发生的情况。

以下是您的数据生成的图表图片(颜色为1 =红色,2 =绿色,3 =蓝色):

Graph

main()内的循环从3开始,然后按红色查找2,然后调用dfs(2, red);。 (这已经有点奇怪,因为您可能刚刚调用dfs(3, red)来获得相同的结果)。但是dfs函数紧跟在它找到的第一个红色边缘之后,因此它最终在21之间来回穿梭。

为避免这种情况,您需要为dfs添加一种方法,让他们知道不要重新访问已访问过的节点。实际上,您已经跟踪vist,但未在dfs函数中进行检查。

我认为只需将if ( vist[u] ) return 0;添加到该函数的开头即可解决此图的问题。不过,我认为您应该为每种颜色重置vist0 的所有内容,而不仅仅是针对每个测试用例。例如,在此图表中,如果从24但不是从34有蓝色边缘,搜索将永远找不到它,因为2在红色搜索期间已被标记为访问过。