CF1060 E-Sergey and Subway
Posted le-mon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}
以上是关于CF1060 E-Sergey and Subway的主要内容,如果未能解决你的问题,请参考以下文章