星尘斗士 (stars)

星尘斗士 (stars)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

请开 long long

若众人皆丧气,则我谒见谏言。———— R a i n y 7 Rainy7 Rainy7

在浩瀚无垠的宇宙中,分布着许许多多的文明,它们之间经常起冲突。

一次,一个文明派出大批星舰进攻地球,地球人被打得落荒而逃。

此时在地球上,巨神 R a i n y 7 Rainy7 Rainy7 天天吊打集训队,已经感到厌烦了,于是, R a i n y 7 Rainy7 Rainy7 便去吊打外星人了。

R a i n y 7 Rainy7 Rainy7 使用魔法,将这 n n n 艘星舰封锁住了。然而,这些星舰都有护盾保护, R a i n y 7 Rainy7 Rainy7 要想方设法破除它们。

星舰的封锁关系可以看成一棵树。一开始, R a i n y 7 Rainy7 Rainy7 可以任选一艘星舰,然后直接解除它的护盾。紧接着, R a i n y 7 Rainy7 Rainy7 可以进行 n n n 次操作,每次选择一艘未被护盾保护的星舰,然后直接摧毁它,并且获得它被摧毁前所在的全都是未被摧毁的星舰的连通块的大小的魔法值。一艘星舰被摧毁后,与它直接相连且未被摧毁的星舰的护盾会全部被解除。

R a i n y 7 Rainy7 Rainy7 想知道,自己最多能获得多少魔法值。她只用了 11451 4 − 1919810 114514^{-1919810} 1145141919810s就解决了问题,于是把问题抛给了您。
在这里插入图片描述

如图所示,加粗的星舰表示已经被摧毁。若选择 2 2 2 号星舰,将会获得 4 4 4 点魔法值,并且解除 3 , 5 , 6 3,5,6 3,5,6 的护盾。若选择 9 9 9 号星舰,将会获得 3 3 3 点魔法值,并且解除 7 , 8 7,8 7,8 的护盾。

输入

第一行一个数 n n n,表示星舰数量。
接下来 n − 1 n-1 n1 行,每行两个数 u , v u,v u,v,表示星舰的相连关系。

输出

一行一个数,表示最多能获得的魔法值。

样例输入

【样例1】

9
1 2
2 3
2 5
2 6
1 4
4 9
9 7
9 8

【样例2】

5
1 2
1 3
2 4
2 5

样例输出

【样例1】

36

【样例2】

14

数据范围

2 ≤ n ≤ 2 × 1 0 5 2 \leq n \leq 2 \times10^5 2n2×105

思路

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
typedef long long ll;
template <typename T>
inline void read(T &x) {
    x = 0;
    static int p;
    p = 1;
    static char c;
    c = getchar();
    while (!isdigit(c)) {
        if (c == '-')p = -1;
        c = getchar();
    }
    while (isdigit(c)) {
        x = (x << 1) + (x << 3) + (c - 48);
        c = getchar();
    }
    x *= p;
}
template <typename T>
inline void print(T x) {
    static int cnt;
    static int a[50];
    cnt = 0;
    do {
        a[++cnt] = x % 10;
        x /= 10;
    } while (x);
    for (int i = cnt; i >= 1; i--)putchar(a[i] + '0');
    puts("");
}
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5+10;
int n;
ll ans;
int siz[maxn];
vector<int>e[maxn];
int f[maxn];
ll dp1[maxn];
ll dp2[maxn];
void dfs1(int u,int fa) {
    siz[u] = 1;
    for (int v:e[u]) {
        if (v == fa) continue;
        f[v]=u;
        dfs1(v, u);
        siz[u] += siz[v];
        dp1[u] += dp1[v];
    }
    dp1[u] += siz[u];
}
void dfs2(int u,int fa) {
    if (u != fa) {
        dp2[u] = dp1[fa] - siz[fa] + dp2[fa] - dp1[u] + n - siz[u];
    }
    for (int v:e[u]) {
        if (v == fa) continue;
        dfs2(v, u);
    }
}
inline void work() {
    read(n);
    for (int i = 1, u, v; i < n; i++) {
        read(u);
        read(v);
        e[u].emplace_back(v);
        e[v].emplace_back(u);
    }
    dfs1(1, 0);
    dfs2(1, 1);
    for (int i = 1; i <= n; i++) {
        ans = max(ans, dp1[i] + dp2[i] - siz[i]);
    }
    print(ans + n);
}
int main() {
    int T = 1;
    //scanf("%d", &T);
    while (T--) {
        work();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值