【BZOJ1040】骑士(基环树,树形DP)

题意:有一张N点N边的图,点有点权。相连的两个点不能同时取,问使点权和最大怎么取。

思路:如果是N点N-1边就是一棵树,即”没有上司的舞会“

        现在多了一条边,就是环套树的森林。我们枚举删哪条边,删后就是一棵树,做树形DP取最大值即可。删掉的边所连接的两个点中有一个点要强制不取。

 1 var f:array[1..1100000,0..1]of int64;
 2     head,vet,next,flag,a:array[1..2100000]of longint;
 3     n,i,tot,st,ed,ban,x:longint;
 4     tmp,ans:int64;
 5 
 6 procedure add(a,b:longint);
 7 begin
 8  inc(tot);
 9  next[tot]:=head[a];
10  vet[tot]:=b;
11  head[a]:=tot;
12 end;
13 
14 function max(x,y:int64):int64;
15 begin
16  if x>y then exit(x);
17  exit(y);
18 end;
19 
20 procedure dfs(u,pre:longint);
21 var e,v:longint;
22 begin
23  flag[u]:=1;
24  e:=head[u];
25  while e<>0 do
26  begin
27   v:=vet[e];
28   if v<>pre then
29   begin
30    if flag[v]=1 then
31    begin
32     st:=u; ed:=v; ban:=e;
33    end
34     else dfs(v,u);
35   end;
36   e:=next[e];
37  end;
38 end;
39 
40 function fan(x:longint):longint;
41 begin
42  if x mod 2=0 then exit(x-1)
43   else exit(x+1);
44 end;
45 
46 procedure dp(u,pre:longint);
47 var e,v:longint;
48 begin
49  f[u,0]:=0; f[u,1]:=a[u];
50  e:=head[u];
51  while e<>0 do
52  begin
53   v:=vet[e];
54   if (e<>ban)and(v<>pre)and(e<>fan(ban)) then
55   begin
56    dp(v,u);
57    f[u,0]:=f[u,0]+max(f[v,0],f[v,1]);
58    f[u,1]:=f[u,1]+f[v,0];
59   end;
60   e:=next[e];
61  end;
62 end;
63 
64 begin
65 
66  read(n);
67  for i:=1 to n do
68  begin
69   read(a[i],x);
70   add(i,x);
71   add(x,i);
72  end;
73  for i:=1 to n do
74   if flag[i]=0 then
75   begin
76    st:=0; ed:=0; ban:=0;
77    dfs(i,-1);
78    dp(st,-1);
79    tmp:=f[st,0];
80    dp(ed,-1);
81    tmp:=max(tmp,f[ed,0]);
82    ans:=ans+tmp;
83   end;
84  writeln(ans);
85 
86 end.

 

 

    

posted on 2016-11-09 10:40  myx12345  阅读(277)  评论(0编辑  收藏  举报

导航