【距离GDKOI:44天&GDOI:107天】【BZOJ1040】[ZJOI2008] 骑士 (环套树DP)

    其实已经准备退役了,但GDOI之前还是会继续学下去的!!当成兴趣在学,已经对竞赛失去信心了的样子,我还是回去跪跪文化课吧QAQ

    第一道环套树DP...其实思想挺简单的,就把环拆开,分类处理。若拆成开的两个点是u,v,dp[i,0..1]分别表示第i位骑士不选和选

    (1) 不选u,v点随意    (2)u随意,v点不选...

    分类dp处理即可

  1 const maxn=1000419;
  2 type
  3  edgetype=record
  4   toward,next:longint;
  5  end;
  6 
  7 var
  8  edge:array[0..maxn*2] of edgetype;
  9  first:array[0..maxn] of longint;
 10  val:array[0..maxn] of int64;
 11  dp:array[0..maxn,0..1] of int64;
 12  pd,vb,vc:array[0..maxn] of boolean;
 13  root,vv,e,tot:longint;
 14  n:longint;
 15 function max(x,y:int64):int64; begin if x>y then exit(x) else exit(y); end;
 16 
 17 procedure addedge(i,j:longint);
 18 begin
 19  edge[tot].toward:=j;
 20  edge[tot].next:=first[i];
 21  first[i]:=tot;
 22  inc(tot);
 23 end;
 24 
 25 procedure add(i,j:longint);
 26 begin
 27  addedge(i,j); addedge(j,i);
 28 end;
 29 
 30 procedure dfs(v,fa:longint);
 31 var i,tmp:longint;
 32 begin
 33  pd[v]:=true;
 34  i:=first[v];
 35  while i<>-1 do
 36   begin
 37    tmp:=edge[i].toward;
 38    if not pd[tmp] then dfs(tmp,v)
 39     else if tmp<>fa then
 40      begin
 41       vv:=v;
 42       root:=tmp;
 43       e:=i;
 44      end;
 45    i:=edge[i].next;
 46   end;
 47 end;
 48 
 49 procedure dpb(v:longint); //ban u
 50 var i,tmp:longint;
 51 begin
 52  dp[v,0]:=0; dp[v,1]:=val[v]; vb[v]:=true;
 53  i:=first[v];
 54  while i<>-1 do
 55   begin
 56    tmp:=edge[i].toward;
 57    if (i<>e) and (i xor 1<>e) and not vb[tmp] then
 58     begin
 59      dpb(tmp);
 60      dp[v,0]:=dp[v,0]+max(dp[tmp,0],dp[tmp,1]);
 61      dp[v,1]:=dp[v,1]+dp[tmp,0];
 62     end;
 63    i:=edge[i].next;
 64   end;
 65 end;
 66 
 67 procedure dpc(v:longint); //ban v;
 68 var i,tmp:longint;
 69 begin
 70  dp[v,0]:=0; dp[v,1]:=val[v]; vc[v]:=true;
 71  i:=first[v];
 72  while i<>-1 do
 73   begin
 74    tmp:=edge[i].toward;
 75    if (i<>e) and (i xor 1 <>e) and not vc[tmp] then
 76     begin
 77      dpc(tmp);
 78      dp[v,1]:=dp[v,1]+dp[tmp,0];
 79      if tmp=vv then dp[v,0]:=dp[v,0]+dp[tmp,0]
 80       else dp[v,0]:=dp[v,0]+max(dp[tmp,0],dp[tmp,1]);
 81     end;
 82    i:=edge[i].next;
 83   end;
 84 end;
 85 
 86 procedure solve;
 87 var i:longint;
 88  rec,ans:int64;
 89 begin
 90  ans:=0;
 91  for i:= 1 to n do
 92   if not pd[i] then
 93    begin
 94     rec:=0; root:=-1; dfs(i,-1);
 95     dpb(root); rec:=dp[root,0];
 96     dpc(root); rec:=max(rec,max(dp[root,0],dp[root,1]));
 97     inc(ans,rec);
 98    end;
 99  writeln(ans);
100 end;
101 
102 procedure init;
103 var i,x:longint;
104 begin
105  fillchar(first,sizeof(first),255);
106  readln(n);
107  tot:=0;
108  for i:= 1 to n do
109   begin
110    readln(val[i],x);
111    add(i,x);
112   end;
113 end;
114 
115 Begin
116  init;
117  solve;
118 End.
原文地址:https://www.cnblogs.com/EC-Ecstasy/p/4224760.html