72 条题解
-
0eiwoqu LV 5 @ 2008-10-07 14:19:00
向大牛们咨询一个问题:这道题怎么就不存在有一个点是有2个入度呢?
我都服了,比赛的时候本来向用朴素写一个,但是考虑到有可能有这种情况,所以就直接写了一个FLOYD,结果过了2个。 -
02008-10-06 20:22:01@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 134ms
├ 测试数据 07:运行时错误...| 错误号: 202 | 堆栈溢出错
├ 测试数据 08:答案正确... 462ms
├ 测试数据 09:答案正确... 509ms
├ 测试数据 10:运行时错误...| 错误号: 202 | 堆栈溢出错var
z:int64;
h,v,g:array[1..20004]of int64;
s:array[1..20004,1..3]of int64;
a,b,c,n,m,i,j,t,q:longint;
procedure dfs(l1,l2:longint);
var
k,i,l3:longint;
begin
k:=l1;
i:=0;
repeat
{while u -
02008-10-06 12:00:53@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms
不用非递归也能全0ms啊。数组模拟链表+dfs,结束时间戳f的等号不能掉啊,害的我一直wa,还有结果和距离要用int64。 -
02008-10-05 20:26:53@
var
n,i,u,v:0..10000;
m,j:0..100000;
fathers:array[0..10000]of 0..10000;
times:array[0..10000]of dword;
time,father,sum,sumtime:int64;
could:boolean;
begin
readln(n,m);
for i:=1 to n-1 do
begin
read(time,father);
fathers[father]:=time;
readln(time);
times[father]:=time
end;sumtime:=0;
sum:=0;
for j:=1 to m do
begin
readln(u,v);
father:=v;
time:=0;
could:=true;
while (fatheru) do
begin
time:=time+times[father];
father:=fathers[father];
if (father=1) and(u1) then begin could:=false; break end;
end;
if could then begin sum:=sum+1; sumtime:=sumtime+time end;
end;
writeln(sum);
writeln(sumtime);
end.有谁帮我看看。
思路:记录每个节点的父节点(fathers)和到父节点的时间(times);
从最低点(v)搜索,如果最高点是它的父节点(u),那么,记录时间,退出;
如果搜到底(第一个点)还没有结果,就退出。
但有若干个点运行超时...
谁能帮我? -
02008-10-03 22:23:31@
正确的0S出解的方法是:
先用邻接表记录父子关系,然后遍历整棵树,用一个数组BIN记录第一次遍历到某个接点的时间T,用EN数组记录最后一次遍历到某个接点的时间T(即遍历完该接点的所有子接点后返回该接点的时刻),这种方法即称为时间戳,可以用来判断A是否可以到达B..判断的依据是(BIN[A]=EN)TRUE 则可以到达.注意遍历要用非递归写,因为N最大有10000,意味着程序最多可能搜10000层,这对评测机是吃不消的... 看来DFS的非递归也很重要啊!
-
02008-10-03 18:34:03@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:运行时错误...| 错误号: 202 | 堆栈溢出错
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:运行时错误...| 错误号: 202 | 堆栈溢出错
怎么回事?
program rally;
type
link=^rec;
rec=record
w:longint;
next:link;
end;
var
a,b:array[1..10000]of link;
f,fa,c,d:array[0..10000]of longint;
root,n,m,i,k,u,vv,t,way:longint;
ans,sum:qword;
v:array[1..10000]of boolean;
p:link;
function find(x:longint):longint;
begin
if f[x]x then f[x]:=find(f[x]);
exit(f[x]);
end;
function dist(x,y:longint):qword;
begin
{writeln(x,' ',y);
writeln(d[x],' ',d[y]);}
dist:=d[x]-d[y];
end;
procedure search(x:longint);
var g,h:longint;
p:link;
begin
v[x]:=true; p:=b[x];
while pnil do
begin
if v[p^.w] then
begin
h:=find(p^.w);
if h=p^.w then
begin inc(sum); inc(ans,dist(x,p^.w)); end;
end;
p:=p^.next;
end;
f[x]:=x; p:=a[x];
while pnil do
begin
search(p^.w);
p:=p^.next;
end;
f[x]:=fa[x];
end;
procedure dfs(x:longint);
var p:link;
begin
p:=a[x];
while pnil do
begin
d[p^.w]:=d[x]+c[p^.w];
dfs(p^.w);
p:=p^.next;
end;
end;
begin
assign(input,'rally.in'); reset(input);
assign(output,'rally.out'); rewrite(output);
readln(n,m);
fillchar(v,sizeof(v),0);
for i:=1 to n-1 do
begin
readln(u,vv,t); v[vv]:=true;
fa[vv]:=u; c[vv]:=t;
new(p); p^.w:=vv;
p^.next:=a; a:=p;
end;
for i:=1 to n do
if not v[i] then
begin root:=i; break; end;
fillchar(v,sizeof(v),0);
for i:=1 to m do
begin
readln(u,vv);
new(p); p^.w:=u;
p^.next:=b[vv]; b[vv]:=p;
end;
ans:=0; sum:=0; way:=0; d[root]:=0;
dfs(root);
search(root);
writeln(sum); writeln(ans);
close(input); close(output);
end. -
02008-10-03 17:45:51@
用邻接表好做但是只能针对现有的数据,来一个节点1有9999个儿子就挂了。。所以是非完美算法。
-
02008-10-03 16:08:59@
每个点不会超过100个孩子,开个10000*100的表就可以...
然后DFS记录每个点的开始和结束时间...
-
02008-10-03 15:53:18@
前向星存图,要用long long存距离
-
02008-10-03 14:49:42@
时间戳是个好东西啊,我来解释一下吧。记录dfs第一次访问时间st,记录离开时间en,如果有(st[x]=en[y])那么这样子就是合法的。
当时做的时候我竟然搞了个10000*10000的数组,bs下自己
答楼下:没错,如果B的访问时间比A大,那么B的完成时间一定比A大,在同一层嘛,B的完成时间还要加上A的 -
02008-10-03 14:21:14@
为什么存取非法???
-
02008-10-03 14:37:00@
感觉解体报告有错
期望得分:50~60
◆方法二:
对图进行一次dfs,记录每个点第一次被访问到的时间戳begin[i]和完成以这个点为根的树的时间戳finish[i]。则u是v的祖先的充要条件是
Begin -
02008-10-03 19:41:54@
dfs一次把时间戳和距离到根弄出来。 O(n)
询问,b的时间戳被a包含b就是a的后代,然后把距离作差就是第二问,O(m)
O(m+n)
PS:指针+非递归啊....谁说是非完美算法...
-
02008-10-03 12:43:57@
第一问LCA:
最近公共祖先(LCA):
对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点。要高效解决LCA问题,我们要先介绍RMQ问题:
RMQ问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j
-
02008-10-03 17:41:26@
经测试每个点不超过15个儿子,开10000*15的邻接表可以AC,编程难度下降
DFS记时间戳···· -
02008-10-03 09:39:15@
搜一遍+并查集,一次性秒杀
-
02008-10-03 09:23:51@
呃……这道题居然对了,我的方法很锉……
询问u到v可不可以,就是说LCA(u , v)等不等于u。
然后用LCA的tarjan算法,统计一下哪两个点之间可以走。
第二问顺着过一下就行了。 -
02008-10-02 14:40:42@
又是车
-
02008-10-01 16:57:51@
啊
-
02008-10-01 13:22:39@
为什么还是你...