zoukankan      html  css  js  c++  java
  • 2019江西省赛A题题解与代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<string>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=100010;
    const int inf=0x3f3f3f3f;
    int h[N],ne[N],idx;
    int st[N];
    int n;
    int tot;
    struct node{
        int u;
        int v;
        int to;
    };
    node e[2*n];
    void add(int a,int b){
        e[idx].u=a;
        e[idx].v=b;
        e[idx].to=h[a];
        h[a]=idx++;
    }
    void dfs(int u){
        int i;
        if(st[u])
        return ;
        st[u]=true;
        tot++;
        for(i=h[u];i!=-1;i=e[i].to)
        dfs(e[i].v);
    }
    int p,tmp;
    int dfs1(int u,int fa,int n){
        int i;
        int tot=0;
        int sum=0;
        int ans=0;
        for(i=h[u];i!=-1;i=e[i].to){
            int j=e[i].v;
            if(j==fa)
            continue;
           tot=dfs1(j,u,n);
           ans=max(ans,tot);
           sum+=tot; 
        }
        ans=max(ans,n-sum-1);
        if(ans<tmp){
            tmp=ans;
            p=u;
        }
        return sum+1;
    }
    ll res;
    
    int dfs2(int u,int fa){
        int i;
        int t=0;
        int sum=0;
        for(i=h[u];i!=-1;i=e[i].to){
            int j=e[i].v;
            if(j==fa)
            continue;
            t=dfs2(j,u);
            res+=(1ll*t)*(1ll*(n-t));
            sum+=t;
        }
        return sum+1;
    }
    
    int main(){
        scanf("%d",&n);
        memset(h,-1,sizeof h);
        int i;
        int u,v;
        for(i=0;i<n-2;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        int root1,root2,n1,n2;
        for(i=1;i<=n;i++){
            if(!st[i]){
                tot=0;
                dfs(i);
                if(i==1){
                 root1=1;
                 n1=tot;
                }
                else{
                    root2=i;
                    n2=tot;
                }
            }
        }
        int g1,g2;
        tmp=inf;
        dfs1(root1,-1,n1);
        g1=p;
        tmp=inf;
        dfs1(root2,-1,n2);
        g2=p;
        add(g1,g2);
        add(g2,g1);
        dfs2(1,-1);
        printf("%lld\n",res);
        return 0;
    }
    View Code

    本题是动态规划当中的树形dp问题 本质上是求解树的重心。

    通过dfs分别求解两树的重心后相连,在合并的树上求解距离和

    距离和表示为每条边左节点和右节点个数的乘积(考虑这条边在每两个点的路径上的贡献度)

    树的重心定义为除去该点后联通子树的节点数最大值最小的点。

    性质:

    1.每个树最多有两个重心,若存在两个重心则两个重心必相邻。

    2.两个树合并后的重心在两树重心连线上。

  • 相关阅读:
    语言特性-上下文对象
    语言特性-闭包
    语言特性-变量作用域
    语言特性-函数重载与类型检查
    面向对象的JS代码
    单例模式
    wait操作接口
    进程的创建模型
    模拟密码登陆过程
    目录操作的一些函数理解
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12003509.html
Copyright © 2011-2022 走看看