luogu P2607 [ZJOI2008] 骑士 树dp

Posted yuyanjiab

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P2607 [ZJOI2008] 骑士 树dp相关的知识,希望对你有一定的参考价值。

传送门

又一个没有上司的舞会

这个dp有环 妈妈怎么办啊

要不...环上随便断一条边?

然后最后选的时候分别取两个根节点不选的情况的最大值

几个要点:

1.图可能是多个环套树 要循环走完

2.不能只记录顶点 因为如果有重边的话会把二元环筛掉

3.位运算优先级... 要写成(i^1)==cntline

Time cost inf

这题从上周就开始D

一度放弃 今天想整一下以前做过的所有题然后就

就写出来啦!!(开心)

技术分享图片

Code:

(边界写的比较奇怪 是Debug的时候被吓怕了)

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<vector>
 6 #define ms(a,b) memset(a,b,sizeof a)
 7 #define inf 2147483647
 8 #define rep(i,a,n) for(int i = a;i <= n;i++)
 9 #define per(i,n,a) for(int i = n;i >= a;i--)
10 using namespace std;
11 typedef long long ll;
12 int read() {
13     int as = 0,fu = 1;
14     char c = getchar();
15     while(c<0||c>9) {
16         if(c == -) fu = -1;
17         c = getchar();
18     }
19     while(c<=9&&c>=0) {
20         as = as * 10 + c - 0;
21         c = getchar();
22     }
23     return as * fu;
24 }
25 const int N = 1000005;
26 //head
27 int n;
28 int head[N],nxt[N<<1],mo[N<<1],cnt = -1;
29 void _add(int x,int y) {
30     mo[++cnt] = y;
31     nxt[cnt] = head[x];
32     head[x] = cnt;
33 }
34 void add(int x,int y) {if(x^y)_add(x,y),_add(y,x);}
35 
36 int rt1,rt2,Cntline;
37 bool vis[N];
38 void dfs(int x,int f) {
39     vis[x] = 1;
40     for(int i = head[x];~i;i = nxt[i]) {
41         int sn = mo[i];
42         if(sn == f) continue;
43         if(!vis[sn]) dfs(sn,x);
44         else {
45             rt1 = x,rt2 = sn;
46             Cntline = i;
47         }
48     }
49 }
50 
51 int v[N];
52 ll dp[N][2];
53 void Dp(int x,int f) {
54     dp[x][0] = 0,dp[x][1] = v[x];
55     for(int i = head[x];~i;i = nxt[i]) {
56         int sn = mo[i];
57         if(sn == f) continue;
58         if(i == Cntline || ((i ^ 1) == Cntline)) continue;
59         // printf("%d->%d
",x,sn);
60         Dp(sn,x);
61         dp[x][0] += max(dp[sn][0],dp[sn][1]);
62         dp[x][1] += dp[sn][0];
63     }
64 }
65 
66 int main() {
67     ms(head,-1);
68     n = read();
69     rep(i,1,n) {
70         v[i] = read();
71         add(i,read());
72     }
73     ll ans = 0,maxx;
74     rep(i,1,n) {
75         maxx = 0;
76         if(vis[i]) continue;
77         rt1 = rt2 = Cntline = -2;
78         dfs(i,-1);
79         // printf("%d %d %d
",rt1,rt2,Cntline);
80         Dp(rt1,rt1),maxx = dp[rt1][0];
81         // printf("#%d
",maxx);
82         Dp(rt2,rt2),maxx = max(maxx,dp[rt2][0]);
83         // printf("#%d
",maxx);
84         ans += maxx;
85     }
86     printf("%lld
",ans);
87     return 0;
88 }
View Code

以上是关于luogu P2607 [ZJOI2008] 骑士 树dp的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P2607 [ZJOI2008]骑士

P2607 [ZJOI2008]骑士

P2607 [ZJOI2008]骑士

P2607 [ZJOI2008]骑士

题解ZJOI2008骑士

luogu2607/bzoj1040 [ZJOI2008]骑士 (基环树形dp)