【发布时间】:2012-10-26 13:21:52
【问题描述】:
我试图解决这个问题 Problem Description 似乎正确的想法是检查给定的图是否有循环(是否是树)。但是,我的代码无法通过测试 7,(总是超过时间限制),知道如何让它更快吗?我使用了 DFS。非常感谢 是的,终于被录取了。问题是每个顶点上的dfs,这是不必要的。 dfs函数应该是这样的。
function dfs(idx: integer; id: integer): boolean;
begin
if (visited[idx] = id) then
begin
Result := false;
Exit;
end;
if (tree[idx] <> 0) then
begin
visited[idx] := id;
Result := dfs(tree[idx], id);
Exit;
end;
Result := true;
end;
program Project2;
{$APPTYPE CONSOLE}
var
i, m, j, n, k: integer;
tree: array [1 .. 25001] of integer;
visited: array [1 .. 25001] of boolean;
function dfs(idx: integer): boolean;
label
fin;
var
buf: array[1 .. 25001] of integer;
i, cnt: integer;
begin
cnt := 1;
while (true) do
begin
if (visited[idx]) then
begin
Result := false;
goto fin;
end;
if (tree[idx] <> 0) then
begin
visited[idx] := true;
buf[cnt] := idx;
Inc(cnt);
idx := tree[idx];
end
else
begin
break;
end;
end;
Result := true;
fin:
for i := 1 to cnt - 1 do
begin
visited[buf[i]] := false;
end;
end;
function chk(n: integer): boolean;
var
i: integer;
begin
for i := 1 to n do
begin
if (tree[i] = 0) then continue;
if (visited[i]) then continue;
if (dfs(i) = false) then
begin
Result := false;
Exit;
end;
end;
Result := true;
end;
begin
Readln(m);
for i := 1 to m do
begin
Readln(n);
k := 0;
for j := 1 to n do
begin
Read(tree[j]);
if (tree[j] = 0) then
begin
Inc(k);
end;
end;
if (k <> 1) then
begin
Writeln('NO');
end
else
if (chk(n)) then
begin
Writeln('YES');
end
else
begin
Writeln('NO');
end;
Readln;
end;
//Readln;
end.
【问题讨论】:
-
一般的经验法则是递归比迭代慢。如果可能,尝试使用 bfs?
-
好吧,我同意。但我已经通过使用缓冲区数组取消标记访问数组来删除“递归”。此外,我认为 DFS 发现周期更快....
-
您当然可以使用树的已知属性,比如边数与顶点数的关系,以避免大部分工作?您需要为每个连接的组件执行此操作。
-
@FUD:声明是错误的。我对它进行了基准测试(并在统计上证明)in this thread 用于迭代/递归快速排序。您需要对堆栈进行非常优化的实现(针对特定需求)才能使该声明成立。
-
一个图是一棵树当且仅当它 (1) 是连通的并且 (2) 没有环。这些 (1) 和 (2) 等价于 @amit 给出的 (1) 和 (2)。
标签: algorithm graph tree pascal