描述
There are initially N−1 pairs of friends among FJ’s N cows labeled 1…N, forming a tree. The cows are
leaving the farm for vacation one by one. On day i, the i th cow leaves the
farm, and then all pairs of the i th cow’s friends still present on the farm
become friends.
For each i from 1 to N, just before the i th cow leaves, how many
ordered triples of distinct cows (a,b,c) are there such that none of a,b,c
are on vacation, a is friends with b, and b is friends with c?
农夫约翰有 N 头奶牛,编号 1∼N。
最初时,奶牛之间有 N−1 对两两朋友关系,这些关系可以构成一棵树。
假期来临,奶牛们一只接着一只的离开农场去度假。
在第 i 天,第 i 头奶牛会离开农场,并且在它离开后,所有仍在农场的第 i 头奶牛的朋友两两之间都会成为朋友。
对于从 1 到 N 的每个 i,请你计算,在第 i 头奶牛即将离开之时(轮到它离开了,但它还没离开),有多少个有序奶牛三元组 (a,b,c) 满足奶牛 a,b,c 仍在农场,且 a 和 b 是朋友,b 和 c 是朋友。
输入描述
The first line contains N.
The next N−1 lines contain two integers ui and vi denoting that cows
ui and vi are initially friends.
第一行包含整数 N。
接下来 N−1 行,每行包含两个整数 ui,vi,表示奶牛 ui 和 vi 最初是朋友。
输出描述
The answers for i from 1 to N on separate lines.
共 N 行,第 i 行输出在第 i 头奶牛即将离开之时,满足条件的有序奶牛三元组的数量。
样例输入 1
3 1 2 2 3
样例输出 1
2 0 0
样例输入 2
4 1 2 1 3 1 4
样例输出 2
6 6 0 0
样例输入 3
5 3 5 5 1 1 4 1 2
样例输出 3
8 10 2 0 0
提示
数据范围与提示
2≤N≤2×105,1≤ui,vi≤N
For the first sample:
(1,2,3) and (3,2,1) are the triples just before cow 1 leaves.
After cow
1 leaves, there are less than 3 cows left, so no triples are possible.
For the second sample:
At the beginning, cow 1 is friends with all other cows, and no other pairs of
cows are friends, so the triples are (a,1,c) where a,c are different cows
from {2,3,4}, which gives 3⋅2=6 triples.
After cow 1 leaves, the remaining three cows are all friends, so the triples
are just those three cows in any of the 3!=6 possible orders.
After cow 2 leaves, there are less than 3 cows left, so no triples are
possible.
2≤N≤2⋅105, 1≤ui,vi≤N.
- Inputs 4-5: N≤500.
- Inputs 6-10: N≤5000.
- Inputs 11-20: No additional constraints.
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
int n,vis[200005],ffa[400005],fa[400005];
ll ans,f[400005],g[400005],h[400005];
vector<int>e[400005];
int root(int x){
if(x==fa[x])return x;
return fa[x]=root(fa[x]);
}
ll qur(int x){
if(!x)return 0;
return (f[x]+1)*f[x]*(f[x]-1)-f[x]*f[x]+2*f[x]*h[x];//统计一个点的答案
}
void dfs(int u,int ft){
ffa[u]=ft;
for(auto v:e[u]){
if(v==ft)continue;
dfs(v,u);
if(u<=n)g[u]+=f[v];
else{
f[u]++;
h[u]+=g[v];
}
}
}
void del(int u){
int f1=root(ffa[u]),f2=ffa[f1],f3=root(ffa[f2]);
ans-=g[u]*g[u];
ans-=qur(f1)+g[f2]*g[f2]+qur(f3);
f[f1]--;g[f2]--;h[f3]--;
for(auto v:e[u]){
if(v==ffa[u])continue;
ans-=qur(v);
fa[v]=f1;
f[f1]+=f[v];
g[f2]+=f[v];
h[f1]-=f[v];h[f1]+=h[v];
h[f3]+=f[v];
}
ans+=qur(f1)+g[f2]*g[f2]+qur(f3);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<n;++i){
int a,b;
cin>>a>>b;
e[a].pb(n+i);e[n+i].pb(a);
e[b].pb(n+i);e[n+i].pb(b);
}
dfs(n,0);
for(int i=1;i<=n;++i)ans+=g[i]*g[i];
for(int i=n+1;i<=2*n-1;++i)ans+=qur(i);
for(int i=n+1;i<=2*n-1;++i)fa[i]=i;
cout<<ans<<endl;
for(int i=1;i<n;++i){
del(i);//每次先删点进行更新
cout<<ans<<endl;
}
return 0;
}

被折叠的 条评论
为什么被折叠?



