P3478 [POI2008]STA-Station

题意:

给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大

 

发现从根从某个位置移到它的⼀一个⼦子树得出 ans 只要 O(1) 的时间

 

定义 f[u] 代表以 u 为根结点的深度和 

假设 v 是 u 的儿子 ,那么 f[v] 其实就是 v 的子树的深度全部 -1 ,其他节点的深度 + 1

所以我们可以得到 f[v] = f[u] - siz[v] + (n - siz[v]) = f[u] + n - 2 * siz[v]

 

 

#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <math.h>
#include <cstdio>
#include <iomanip>
#include <time.h>
#include <bitset>
#include <cmath>

#define LL long long
#define INF 0x3f3f3f3f
#define ls nod<<1
#define rs (nod<<1)+1

const double eps = 1e-10;
const int maxn = 1e6 + 10;
const LL mod = 1e9 + 7;

int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
using namespace std;

struct edge {
    int v,nxt;
}e[maxn << 1];

int head[maxn];
LL dep[maxn],siz[maxn];
int cnt,n;
LL f[maxn];


inline void add_edge(int u,int v) {
    e[++cnt].v = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}

inline void dfs(int u,int f) {
    siz[u] = 1;
    dep[u] = dep[f] + 1;
    for (int i = head[u];~i;i = e[i].nxt) {
        int v = e[i].v;
        if (v == f)
            continue;
        dfs(v,u);
        siz[u] += siz[v];
    }
}

inline void func(int x,int fa) {
    for (int i = head[x];~i;i = e[i].nxt) {
        int v = e[i].v;
        if (fa == v)
            continue;
        f[v] = f[x] + n - siz[v] - siz[v];
        func(v,x);
    }
}

int main() {
    cnt = 0;
    memset(head,-1, sizeof(head));
    cin >> n;
    for (int i = 1;i < n;i++) {
        int u,v;
        cin >> u >> v;
        add_edge(u,v);
        add_edge(v,u);
    }
    dfs(1,0);
    for (int i = 1;i <= n;i++)
        f[1] += dep[i];
    func(1,0);
    LL ans = 0,idx = 0;
    for (int i = 1;i <= n;i++) {
        if (f[i] > ans) {
            ans = f[i];
            idx = i;
        }
    }
    cout << idx << endl;
    return 0;
}

 

posted @ 2020-02-20 23:12  _Ackerman  阅读(193)  评论(0编辑  收藏  举报