CF1037D Valid BFS?

玄学的题目。。。。

题目大意:

  告诉你一棵树,再告诉你一个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)

猜你喜欢

转载自www.cnblogs.com/by-w/p/9789693.html
今日推荐