【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.
null