#734 (Div. 3) 1551 F. Equidistant Vertices(暴力枚举...)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#734 (Div. 3) 1551 F. Equidistant Vertices(暴力枚举...)相关的知识,希望对你有一定的参考价值。
比赛时没看题,发现是非常暴力的一题,嗯,反正这种写法非常暴力…
当 k = = 2 k==2 k==2时,显然答案是 n ∗ ( n − 1 ) 2 \\frac{n*(n-1)}{2} 2n∗(n−1)
当 k > 2 k>2 k>2时
由于任意两点间的距离都相等,必然存在一个中间点 r r r
满足 d i s ( a 1 , r ) = d i s ( a 2 , r ) = d i s ( a 3 , r ) . . . . dis(a_1,r)=dis(a_2,r)=dis(a_3,r).... dis(a1,r)=dis(a2,r)=dis(a3,r)....
于是我们枚举每个点作为中心点 r r r去 d f s dfs dfs
我们可以枚举 d i s ( a i , r ) dis(a_i,r) dis(ai,r)的距离为 w w w,也就是深度为 w w w
那么枚举 r r r的直接儿子 v 1 , v 2 . . . v s v_1,v_2...v_s v1,v2...vs,处理一个数组 z i [ i ] [ j ] zi[i][j] zi[i][j]表示 i i i子树中深度为 j j j的有多少
显然同属于 i i i子树中的点同时只能选一个,否则中心点 ( l c a ) (lca) (lca)就变成 i i i或者 i i i子树中的节点而不是 r r r
于是枚举深度 w w w后,就是从 z i [ v 1 ] [ w ] , z i [ v 2 ] [ w ] . . . z i [ v s ] [ w ] zi[v_1][w],zi[v_2][w]...zi[v_s][w] zi[v1][w],zi[v2][w]...zi[vs][w]中选出 k k k个的方案
这就变成了一个简单的 d p dp dp,定义 f [ i ] [ j ] f[i][j] f[i][j]表示前 i i i棵子树选 j j j棵的方案数
f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i − 1 ] [ j − 1 ] ∗ z i [ v i ] [ w ] f[i][j]=f[i-1][j]+f[i-1][j-1]*zi[v_i][w] f[i][j]=f[i−1][j]+f[i−1][j−1]∗zi[vi][w]
累加答案即可
枚举中心点 r r r复杂度 O ( n ) O(n) O(n),枚举深度 O ( n ) O(n) O(n), D P DP DP部分 O ( n 2 ) O(n^2) O(n2)
总体复杂度 O ( n 4 O(n^4 O(n4,实际远远跑不满
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 109;
const int mod = 1e9+7;
vector<int>vec[maxn];
int deep[maxn],zi[maxn][maxn],n,k;
void dfs(int u,int father,int rt)
{
deep[u] = deep[father]+1; zi[rt][deep[u]]++;
for(auto v:vec[u] )
{
if( v==father ) continue;
dfs(v,u,rt);
}
}
int f[maxn][maxn],w[maxn];
void upd(int &x,int y){ x = (x+y)%mod; }
int DP()
{
for(int i=1;i<=w[0];i++)
for(int j=0;j<=i && j<=k;j++)
f[i][j] = 0;
f[0][0] = 1;
for(int i=1;i<=w[0];i++)
for(int j=0;j<=i && j<=k;j++)
{
if( j ) upd( f[i][j],f[i-1][j-1]*w[i]%mod );
upd( f[i][j],f[i-1][j] );
}
return f[w[0]][k];
}
signed main()
{
int t; cin >> t;
while( t-- )
{
cin >> n >> k;
for(int i=1;i<n;i++)
{
int l,r; scanf("%lld%lld",&l,&r);
vec[l].push_back( r );
vec[r].push_back( l );
}
if( k==2 ) cout << n*(n-1)/2 << endl;
else
{
int res = 0;
for(int i=1;i<=n;i++)
{
deep[i] = 0;
for(auto v:vec[i] ) dfs(v,i,v);
for(int j=1;j<=n;j++)//枚举深度
{
w[0] = 0;
for(auto v:vec[i] ) w[++w[0]] = zi[v][j];
res = ( res+DP() )%mod;
}
for(auto v:vec[i] )
for(int j=1;j<=n;j++) zi[v][j] = 0;
}
cout << res << endl;
}
for(int i=1;i<=n;i++) vec[i].clear();
}
}
以上是关于#734 (Div. 3) 1551 F. Equidistant Vertices(暴力枚举...)的主要内容,如果未能解决你的问题,请参考以下文章
#734 (Div. 3) 1551. D1,2. Domino (思维,构造easy/hard version)
Codeforces Round #734 (Div. 3)
Codeforces Round #734 (Div. 3)-C. Interesting Story-题解
Codeforces Round #734 (Div. 3)-B1. Wonderful Coloring - 1