CF1187E. Tree Painting[树形dp+换根]

本文探讨了一种基于树形结构的游戏策略优化算法,通过动态规划(DP)的方法,实现对树状游戏中选择路径的最大收益计算。具体地,文章详细介绍了如何通过换根技巧快速更新节点状态,从而达到全局最优解的目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

E. Tree Painting
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a tree (an undirected connected acyclic graph) consisting of n vertices. You are playing a game on this tree.

Initially all vertices are white. On the first turn of the game you choose one vertex and paint it black. Then on each turn you choose a white vertex adjacent (connected by an edge) to any black vertex and paint it black.

Each time when you choose a vertex (even during the first turn), you gain the number of points equal to the size of the connected component consisting only of white vertices that contains the chosen vertex. The game ends when all vertices are painted black.

Let’s see the following example:

Vertices 1 and 4 are painted black already. If you choose the vertex 2, you will gain 4 points for the connected component consisting of vertices 2,3,5 and 6. If you choose the vertex 9, you will gain 3 points for the connected component consisting of vertices 7,8 and 9.

Your task is to maximize the number of points you gain.

Input
The first line contains an integer n — the number of vertices in the tree (2≤n≤2⋅105).

Each of the next n−1 lines describes an edge of the tree. Edge i is denoted by two integers ui and vi, the indices of vertices it connects (1≤ui,vi≤n, ui≠vi).

It is guaranteed that the given edges form a tree.

Output
Print one integer — the maximum number of points you gain if you will play optimally.

Examples
inputCopy
9
1 2
2 3
2 5
2 6
1 4
4 9
9 7
9 8
outputCopy
36
inputCopy
5
1 2
1 3
2 4
2 5
outputCopy
14
Note
The first example tree is shown in the problem statement.

题意:给一棵树,起初每个顶点都是白色,第一轮你可以随意选择一个顶点染成黑色,以后每轮你可以选择已经染成黑色的顶点的相邻白色顶点染色,每轮得到的分数=从当前白色顶点出发,只经过白色顶点可以遍历到的白色顶点数(包括自己)(也就是所选白结点所在白色连通块的大小),求最大总价值

题解:很容易得到根为某个结点的结果,而当根从这个结点向相邻结点转移时只改变了这两个点的某些信息,所以可以很快进行换根后的结果转移,在转移过程更新答案即可

#include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<#x<<" is "<<x<<endl;
typedef long long ll;
const int maxn=2e5+5;
struct edge{
    int fr;
    int to;
    int nex;
}e[maxn<<1];
ll cnt,ans,head[maxn],siz[maxn],dp[maxn];
void adde(int x,int y){
    e[cnt].fr=x;
    e[cnt].to=y;
    e[cnt].nex=head[x];
    head[x]=cnt++;
}
void caldp(int u,int f){
    dp[u]=siz[u];
    for(int i=head[u];i!=-1;i=e[i].nex){
        int v=e[i].to;
        if(v==f)continue;
        caldp(v,u);
        dp[u]+=dp[v];
    }
}
void dfs(int u,int f){
    ans=max(ans,dp[u]);
    for(int i=head[u];i!=-1;i=e[i].nex){
        int v=e[i].to;
        if(v==f)continue;
        dp[u]-=dp[v];
        dp[u]-=siz[v];
        siz[u]-=siz[v];
        dp[v]+=dp[u];
        dp[v]+=siz[u];
        siz[v]+=siz[u];
        dfs(v,u);
        siz[v]-=siz[u];
        dp[v]-=siz[u];
        dp[v]-=dp[u];
        siz[u]+=siz[v];
        dp[u]+=siz[v];
        dp[u]+=dp[v];
    }
}
void calsiz(int u,int f){
    siz[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nex){
        int v=e[i].to;
        if(v==f)continue;
        calsiz(v,u);
        siz[u]+=siz[v];
    }
}
int main(){
    int n;
    scanf("%d",&n);
    memset(head,-1,sizeof(head));
    for(int i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        adde(a,b);
        adde(b,a);
    }
    calsiz(1,-1);
    caldp(1,-1);
    dfs(1,-1);
    printf("%lld\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值