玄学的题目。。。。
题目大意:
告诉你一棵树,再告诉你一个bfs序,问这个bfs序对于这棵树是否合法(从1开始bfs)
拿到这道题的第一感觉发现好像有点麻烦,直接跑个bfs,看看一不一样(貌似还有一大堆的限制)
开始换算法
emmm,经过一段时间的思考,发现直接对着那个bfs序跑一边不就好了吗???
从1开始,我们知道它的孩子一定出现已知的一段区间内,如果这个bfs序合法,那么它的孩子一定在这一段区间中都出现了一次
var
u,v,tot,l,r,i,j,n:longint;
num,fa,head,x,vet,next,size:array[0..400000] of longint;
//num[i]表示结点i上一次是被哪个点拓展的
procedure add(u,v:longint);//链式前向星存边
begin
inc(tot);
next[tot]:=head[u]; head[u]:=tot; vet[tot]:=v;
end;
procedure dfs(id,father:longint);
var point:longint;
begin
fa[id]:=father;//给边定向
point:=head[id];
while point<>0 do
begin
if (vet[point]<>father) then
begin
dfs(vet[point],id);
inc(size[id]);//求结点id孩子的数量
end;
point:=next[point];
end;
end;
begin
readln(n);
for i:=1 to n-1 do
begin
readln(u,v);
add(u,v);
add(v,u);
end;
for i:=1 to n do read(x[i]);
dfs(1,0);
l:=1; r:=1;
if x[1]<>1 then begin writeln('NO'); halt; end;//特判第一个是不是1
for i:=1 to n do
begin
l:=r+1; r:=l+size[x[i]]-1;
//当前这段区间l一定来源于上一段区间r+1,拓展结点便是x[i],长度是x[i]的儿子数量
for j:=l to r do num[x[j]]:=i; //计数
j:=head[x[i]];
while j<>0 do
begin
if (vet[j]<>fa[x[i]]) and (num[vet[j]]<>i) then
begin
writeln('NO');
halt;
end;
j:=next[j];
end;
end;
writeln('YES');
end.
(初赛真的要GG了呀,QAQ,我还小不想AFO)