This page looks best with JavaScript enabled

「HAOI2009」毛毛虫-树形dp

 ·  ✏️ About  380 words  ·  ☕ 1 mins read · 👀... views

对于一棵树,我们可以将某条链和与该链相连的边抽出来,称其为一个“毛毛虫”。求在这个树中点数最多的毛毛虫的点数。

$n < 300000$

链接

Luogu P3174

题解

很简单的一道 $dp$ 题(感觉这个东西像一个 $faKe$ 的 $dp$ )…

随便找一个根,记录 $in[x]$ 为 $x$ 节点的度,令 $d[x]$ 为从 $x$ 节点向下最长的毛毛虫的边数(含 $x$ 连向其他儿子及其连向父节点的边)。

状态转移方程:

$d[x] = \max(d[v]) + in[x]$

统计答案的时候,在 $dfs$ 过程中,我们记录其子树里面的最大的两个 $d$ ,最后更新 $ans = max(ans,d + d’ + in[x])$ 。

最后给 ans +1 。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <cstdio>
#include <vector>
#include <cctype>
using namespace std;

namespace fast_io{
    //...
}using namespace fast_io;

const int MAXN = 310000;

vector<int> edge[MAXN];
int n,m,d[MAXN],in[MAXN],ans = 0;

void dfs(int nown,int fa){
    //d[nown] -> 从nown往下走的最大毛毛虫
    int maxa = 0,maxb = -0x3f3f3f3f;
    for(int i = 0;i<edge[nown].size();i++){
        int v = edge[nown][i];
        if(v == fa) continue;
        dfs(v,nown);
        d[nown] = max(d[nown],d[v]);
        if(d[v] >= maxa)
            maxb = maxa,maxa = d[v];
        else if(d[v] >= maxb)
            maxb = d[v];
    }
    ans = max(ans,maxa+maxb+in[nown]);
    d[nown] += in[nown]-1;
}

void init(){
    read(n),read(m);
    int a,b;
    for(int i = 1;i<=m;i++){
        read(a),read(b);
        edge[a].push_back(b);
        edge[b].push_back(a);
        in[a]++;in[b]++;
    }
}


void solve(){
    dfs(1,0);
    printf("%d\n",ans+1);
}

int main(){
    init();
    solve();
    return 0;
}

cqqqwq
WRITTEN BY
cqqqwq
A student in Software Engineering.


Comments