• Codeforces 1187E


    乍一看题意比较麻烦,好像要删点求联通性,但其实是相当于求以某一个节点为根时,他的所有后代(儿子,儿子的儿子等等)的儿子的总和最大。

    两边dfs即可,第一遍dfs随便找一个点为根,求出每个节点的儿子数siz[],第二遍dfs以每个点作为根更新ans。

    这里注意:如果u为根,u是v的父亲,且此时u后代的和为siz[u] = val,那么v为根时后代和为val-siz[v]+n-siz[v],以此关系作为第二遍dfs的依据、

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2e5 + 5;
    const int inf = 0x3f3f3f3f;
    typedef long long ll;
    int n, tot, head[maxn], siz[maxn];
    struct edge{
        int to, next;
    } ed[maxn<<1];
    ll ans;
    inline void init(){
        memset( head, -1, sizeof(head) );
        tot = 1; ans = 0;
        for( int i=1; i<=n; i++ ) siz[i] = 1;
    }
    
    inline void add( int u, int v ){
        ed[++tot].to = v; ed[tot].next = head[u]; head[u] = tot;
        ed[++tot].to = u; ed[tot].next = head[v]; head[v] = tot;
    }
    
    inline void FindSiz( int x, int fa ){
        for( int i=head[x]; i!=-1; i=ed[i].next ){
            int y =ed[i].to;
            if( y!=fa){
                FindSiz(y, x);
                siz[x] += siz[y];
            }
        }
        ans += siz[x];
    }
    
    inline void dfs( int x, int fa, ll val ){
        for( int i=head[x]; i!=-1; i=ed[i].next ){
            int y = ed[i].to;
            if( y==fa ) continue;
            ll tmp = val-siz[y]+n-siz[y];
            ans = max( ans ,tmp );
            dfs( y, x, tmp );
        }
    }
    
    int main(){
        scanf("%d", &n);
        init();
        for( int i=1; i<n; i++ ){
            int u, v;
            scanf("%d%d", &u, &v);
            add( u, v );
        }
        FindSiz(1, 0);
        dfs( 1, 0, ans );
        printf("%lld
    ", ans);
    
        return 0;
    }
  • 相关阅读:
    kill tomcat with netstat
    windows cmd命令显示UTF8设置
    rtx没有振动功能
    手动加载rvm
    RESTful Java client with Apache HttpClient
    Set Up Git on windows also use github
    lcs.py 最长公共子串算法
    如何:对代理使用 IP 切换
    这个博客站点不错
    a case study
  • 原文地址:https://www.cnblogs.com/WAautomaton/p/11164903.html
Copyright © 2020-2023  润新知