题解:CF2231E Graph Cutting
MaxBlazeResFire · · 题解
感谢这题送我上 Candidate Master!
枚举三者之一的点
直接启发式合并枚举
最后答案除以
::::success[Code]
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define MAXN 2005
int n,d,a[MAXN],dep[MAXN],siz[MAXN],son[MAXN],cnt[MAXN];
int Ans = 0;
vector<int> E[MAXN];
void init( int x , int fa ){
siz[x] = 1,son[x] = 0;
for( int v : E[x] ){
if( v == fa ) continue;
dep[v] = dep[x] + 1,init( v , x ),siz[x] += siz[v];
if( !son[x] || siz[v] > siz[son[x]] ) son[x] = v;
}
}
void modi_single( int x , int fa , int k ){
cnt[dep[x]] += k;
for( int v : E[x] ){
if( v == fa ) continue;
modi_single( v , x , k );
}
}
void chk_single( int x , int fa , int aim ){
if( aim - dep[x] >= 0 && aim - dep[x] < n ) Ans += cnt[aim - dep[x]];
for( int v : E[x] ){
if( v == fa ) continue;
chk_single( v , x , aim );
}
}
void calc( int x , int fa ){
for( int v : E[x] ){
if( v == fa ) continue;
if( v != son[x] ){
calc( v , x );
modi_single( v , x , -1 );
}
}
if( son[x] ) calc( son[x] , x );
int Aim = d - 1 + dep[x];
for( int v : E[x] ){
if( v == son[x] || v == fa ) continue;
chk_single( v , x , Aim ),modi_single( v , x , 1 );
}
if( fa ){
if( Aim - dep[x] >= 0 && Aim - dep[x] < n ) Ans += cnt[Aim - dep[x]];
cnt[dep[x]] ++;
}
}
inline void solve(){
scanf("%lld%lld",&n,&d);
for( int i = 1 ; i < n ; i ++ ){
int u,v; scanf("%lld%lld",&u,&v);
E[u].emplace_back( v ),E[v].emplace_back( u );
}
for( int rt = 1 ; rt <= n ; rt ++ ){
init( rt , 0 ),calc( rt , 0 );
for( int i = 0 ; i <= n ; i ++ ) cnt[i] = siz[i] = son[i] = dep[i] = 0;
}
printf("%lld\n",Ans / 3);
for( int i = 0 ; i <= n ; i ++ ) a[i] = dep[i] = siz[i] = son[i] = cnt[i] = 0,E[i].clear();
Ans = 0;
}
signed main(){
int t; scanf("%lld",&t);
while( t -- ) solve();
return 0;
}
::::