检查周期,程序从图的第一个节点转到图的每个锁定节点->检查其是否在之前访问过,然后再进行一个循环,然后从检查的下一个节点递归重复。 当我自己测试它时,它会起作用,但是当我在潮汐选举中使用它时,它就不会起作用。
问题的解释:https://cs50.harvard.edu/x/2020/psets/3/tideman/
此问题的目标是使用tideman投票算法从选举中选出胜者。 CS50 ide提供了测试功能 Check50 ,我正在尝试修复以下错误: 1.lock_pairs如果创建周期则跳过最后一对 2.lock_pairs如果创建一个循环,则会跳过中间对。
我的逻辑错了吗?
int graph[nodes_count][nodes_count];
bool check_cycle()
{
//if a node is visited during checking cycles visited[]=true
bool visited[nodes_count];
bool circle = false;
return gointo(circle, visited, 0);
}
bool gointo(bool &circle, bool visited[], int to)
{
// start trip form one node in the graph check if it have been visited ( Cycle )
visited[to] = true;
for (int n = 0; n < nodes_count; n++)
{
if (graph[to][n])
{
if (visited[n])
{
circle = true;
}
else
{
gointo(visited, n);
}
break;
}
}
return circle;
}
我的完整解决方案:https://pastebin.com/sbua3EGA
谢谢您的时间,对不起,英语不好:)
答案 0 :(得分:1)
您的算法在无向图中是正确的。在有向图中并不那么明显。
首先,从节点0开始,您可能不会访问所有节点。反例: 1-> 0-> 2
从节点0开始检查时,您将根本不会访问1。如果1也有一个循环的沿,则将不会检测到它。这意味着,您应该为每个顶点进行循环,如果尚未访问,请运行“ gointo”功能。
使用上述更改,您可能最终会发现没有任何变化的周期。
例如:
1-> 2-> 3
4-> 2
如果首先执行gointo(1),则将1、2和3标记为已访问。然后,在调用gointo(4)时,您将“检测到一个循环”,因为4具有已标记顶点的边。这就是为什么您需要两个数组,一个数组告诉您已经访问了该节点,另一个数组告诉该节点在此特定的gointo调用中已被访问。
代码应如下所示:
int graph[nodes_count][nodes_count];
bool check_cycle()
{
//if a node is visited during checking cycles visited[]=true
bool visited[nodes_count];
bool this_call[nodes_count];
bool circle = false;
for (int i = 0; i < nodes_count; ++i)
{
if(!visited[i] && gointo(circle, visited, i))
return true;
}
return false;
}
bool gointo(bool &circle, bool visited[], int to)
{
// start trip form one node in the graph check if it have been visited ( Cycle )
visited[to] = true;
this_call[to] = true;
for (int n = 0; n < nodes_count; n++)
{
if (graph[to][n])
{
if (visited[n] && this_call[n])
{
circle = true;
}
else if(!visited[n])
{
gointo(visited, n);
}
}
}
this_call[to] = false;
return circle;
}