zoukankan      html  css  js  c++  java
  • CF1060 E-Sergey and Subway

    题目戳这里

    一句话题意

    一棵树,任意相隔一个点的两个点连一条新边(原边留下),问所有点对的距离之和。

    Solution

    本来看见是黑题有点怕,但仔细一想也没有那么难。
    先处理出每个点的深度(dep)和子树大小(size),我们把原树上的边称为老边,新建的边是新边。
    首先因为隔了一个点有一条新边,假设新边跨过的点为 u ,那么这条新边产生的价值就是size[i]*(n-size[i])/2,也就是两边点对数量。那么老边会不会产生价值呢?如果原树上两点之间的距离为奇数,那么新图上肯定需要经过一条老边。所以答案还需要加上 (深度为奇的点数×深度为偶的点数)/2。其实还是比较好写的。

    coding

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e5+10;
    struct Tree
    {
        int to,next;
    }e[N*2];
    int n,head[N],cnt,dep[N],size[N];
    long long ans,num;
    void add(int x,int y)
    {
        e[++cnt].to=y;
        e[cnt].next=head[x];
        head[x]=cnt;
    }
    void DFS(int x,int last)
    {
        size[x]=1;
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v==last) continue ;
            dep[v]=dep[x]+1;
            DFS(v,x);
            size[x]+=size[v];
        }
    }
    int main()
    {
        cin>>n;
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        DFS(1,0);
        for(int i=1;i<=n;i++)
        {
            ans+=size[i]*(long long)(n-size[i]);
            if(dep[i]%2==1) num++;
        }
        ans+=num*(long long)(n-num);
        cout<<ans/2;
        return 0;
    }
    
  • 相关阅读:
    linux下的socket编程(3)--server端的简单示例
    高级I/O函数
    补充:memset透彻分析
    空间复杂度为0的数据交换
    排序算法一:直接插入排序
    [Github]watch和star的区别
    计算机网络总结(四)
    计算机网络总结(三)
    Java集合
    计算机网络总结(二)
  • 原文地址:https://www.cnblogs.com/Le-mon/p/9745627.html
Copyright © 2011-2022 走看看