题意:给出一棵树,最开始所有节点都是白的。进行一些操作来计算树的价值。每次操作可以选一个节点,给价值加上包括这个结点在内的白色连通块大小。然后把这个结点染成黑色。除第一次操作外,每次只能选择与黑色结点直接相连的白色结点。求这棵树的最大价值。

解:分析一下就是,每次选一个结点,给价值加上以它为根的子树的大小。选一个结点作为根节点,树的价值就是所有子树大小之和。然后进行一些换根操作。已知一个结点的dp值为它所有结点dp值加上它子树大小,那么把它变成它子节点子树时,就要减去子节点dp值,减去目前子树大小,加上其余子节点子树大小。对子节点处理同理。

直接在昨天代码上改就可以,很快乐(

代码:


#include <bits/stdc++.h>
using namespace std;
#define maxx 200005
#define maxn 25
#define maxm 205
#define ll long long
#define inf 1000000009
#define mod 2520
struct edge{
    int u,v,w,next;
}e[maxx*2];
int head[maxx]={0},cnt=0;
void add(int u,int v){
    e[++cnt].u=u;e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt;
}

int n;
ll ans=0;
ll dp[maxx]={0};
ll son[maxx]={0};
void dfs1(int now,int fa){
    son[now]=1;
    for(int i=head[now];i;i=e[i].next){
        int to=e[i].v;
        if(to==fa) continue;
        dfs1(to,now);
        dp[now]+=dp[to];
        son[now]+=son[to];
    }
    dp[now]+=son[now];
}
void dfs2(int now,int fa){
    ans=max(ans,dp[now]);
    for(int i=head[now];i;i=e[i].next){
        int to=e[i].v;
        if(to==fa) continue;
        dp[now]-=son[to];
        dp[now]-=dp[to];
        son[now]-=son[to];
        dp[to]+=dp[now];
        dp[to]+=son[now];
        son[to]+=son[now];
        dfs2(to,now);
        son[to]-=son[now];
        dp[to]-=son[now];
        dp[to]-=dp[now];
        son[now]+=son[to];
        dp[now]+=dp[to];
        dp[now]+=son[to];
    }
}
signed main() {
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(1,0);
    dfs2(1,0);
    printf("%lld\n",ans);
    return 0;
}

View Code

 

原文地址:http://www.cnblogs.com/capterlliar/p/16885753.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性