1029E.Tree with Small Distances(经典树dp)

Tree with Small Distances

https://ac.nowcoder.com/acm/problem/113026

传送门

观察发现一定是从连出来的边最划算

而且连到一个点之后,这个点周围的所有点都是满足要求的.

定义为和有连边

为通过父亲到

为通过儿子到

那么

那么

但是如果的儿子没有一个和有边,还需要选一个儿子和相连...

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5+10;
struct edge{
    int to,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v)
{
    d[++cnt]=(edge){v,head[u]},head[u] = cnt;
}
int n,f[maxn][3],ans;
//1表示直接相连
//2表示经过父亲再到自己
//3表示经过儿子再到自己 
void dfs(int u,int fa,int dep)
{
    if( dep>=2 )    f[u][1] =1;
    int minn = 1e9;
    for(int i=head[u];i;i=d[i].nxt )
    {
        int v = d[i].to;
        if( v==fa )    continue;
        dfs(v,u,dep+1);
        f[u][1] += min( {f[v][1],f[v][2],f[v][3]} );
        f[u][2] += min( f[v][1],f[v][3] );
        minn = min( minn,f[v][1]-f[v][3] );
    }
    f[u][3] = f[u][2]+max(0,minn);
}
int main()
{
    cin >> n;
    for(int i=1;i<n;i++)
    {
        int l,r; cin >> l >> r;
        add(l,r); add(r,l);
    }
    dfs(1,0,0);
    for(int i=head[1];i;i=d[i].nxt )
        ans += f[d[i].to][1];
    cout << ans;
}
全部评论

相关推荐

点赞 评论 收藏
分享
评论
2
收藏
分享
牛客网
牛客企业服务