【发布时间】:2025-12-13 18:50:01
【问题描述】:
我正在处理一项任务,其中最后一步是获取一组对(其中一对本质上是图中的一条边)并从中制作一个无环图。如果一对碰巧在图中创建了一个循环,则应该跳过它。 DAG 将存储为邻接矩阵(边未加权,因此它的类型为 bool matrix[][] )
根据我在网上阅读的内容,我尝试实施修改后的 DFS。任务是用 C 语言编写的,我是该语言的新手,很抱歉代码的粗糙。 关键是它不会跳过循环形成对,我被困在这一点上。任何建议或帮助表示赞赏。
int MAX; //number of nodes in the graph
int player; //a node in the graph
typedef struct
{
int winner;
int loser;
} pair; //a directed edge from player 'winner' to player 'loser'
pair pairs[MAX * (MAX - 1) / 2]; //array of all valid pairs
int main(void)
{
/* Get input from console for:
MAX - desired number of players, <= 9,
. . .
int results[MAX][MAX]; - a table (2D array), where each element
results[A][B] shows the number of wins that player A
has over player B, and vice versa.
Element results[X][X] = 0 always.
A new pair is only added when two players have unequal
number of wins over each other: results[A][B] != results[B][A],
so that pairs[i].winner is the one having more wins than losses
against pairs[i].loser .
pairs[] is then sorted in descending order according to
the value of pairs[i].winner .
The goal is to create another 2D array
bool matrix[MAX][MAX];
by adding each pair in pairs[] sequentially,
so that matrix[][] is the adjacency matrix of a
Directed Acyclic Graph. (a.k.a. if a pair happens to create
a cycle, it must not be added)
*/
DAG();
}
void DAG(void)
{
int from, to;
for (int i = 0; i < pair_count; i++)
{
//Create an edge in graph
from = pairs[i].winner;
to = pairs[i].loser;
matrix[from][to] = true;
//Check if this edge made a cycle
bool visited[MAX];
bool onStack[MAX];
if (cyclicGraph(visited, onStack))
{
matrix[from][to] = false;
}
//Here we should have the DAG in locked
return;
}
bool cyclicGraph(bool visited[], bool onStack[])
{
for (int k = 0; k < MAX; k++)
{
//Run the hasCycle-DFS only from unvisited vertices
if (!visited[k] && hasCycle(k, visited, onStack))
{
//if it forms a cycle,
return true;
}
}
return false;
}
bool hasCycle(int x, bool visited[], bool onStack[])
{
// we push this 'x' node onto the stack
onStack[x] = true;
int child;
for (int i = 0; i < MAX; i++)
{
if (locked[x][i]) //x's children are only i's holding True values in array "locked[x][i]"
{
child = i;
if (onStack[child])
{
return true;
}
if (!visited[child] && hasCycle(child, visited, onStack))
{
return true;
}
}
}
//we pop the 'x' from the stack and mark it as visited
onStack[x] = false;
visited[x] = true;
return false;
}
【问题讨论】:
-
只有在已经存在从
to到from的路径时,一条边(from,to)才会循环。在添加而不是添加边之前检查这一点更简单,检查整个图的循环,然后如果有则撤消添加。 -
编辑问题以提供minimal reproducible example,包括其他人可以运行以重现问题的完整程序和重现问题的示例输入。
标签: c algorithm graph directed-acyclic-graphs