这是我的代码:
#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()之外。
答案 0 :(得分:2)
在第二种情况下,dfs
函数会导致无限递归。
第一个电话是dfs(u=2, c=1);
,调用dfs(u=1, c=1);
,调用dfs(u=2, c=1);
,然后点击广告。
如果在调试器中运行代码,您应该能够通过在分段错误点输出堆栈跟踪来查看发生的情况。
以下是您的数据生成的图表图片(颜色为1 =红色,2 =绿色,3 =蓝色):
main()
内的循环从3
开始,然后按红色查找2
,然后调用dfs(2, red);
。 (这已经有点奇怪,因为您可能刚刚调用dfs(3, red)
来获得相同的结果)。但是dfs
函数紧跟在它找到的第一个红色边缘之后,因此它最终在2
和1
之间来回穿梭。
为避免这种情况,您需要为dfs
添加一种方法,让他们知道不要重新访问已访问过的节点。实际上,您已经跟踪vist
,但未在dfs
函数中进行检查。
我认为只需将if ( vist[u] ) return 0;
添加到该函数的开头即可解决此图的问题。不过,我认为您应该为每种颜色重置vist
到0
的所有内容,而不仅仅是针对每个测试用例。例如,在此图表中,如果从2
到4
但不是从3
到4
有蓝色边缘,搜索将永远找不到它,因为2
在红色搜索期间已被标记为访问过。