考虑枚举第一个被染色的点 r o o t root root
那么以 r o o t root root为根去遍历整棵树,枚举每对点对 ( u , v ) (u,v) (u,v)计算贡献
若 u u u是 v v v的儿子且满足 v > u v>u v>u,答案直接加一(只有祖先节点被标记自己才会被标记)
若 v v v是 u u u的儿子且满足 u > v u>v u>v,答案直接加一
否则求一个 u , v u,v u,v的 l c a lca lca为 x x x,那么考虑 x x x被染色,接下来想染色 u , v u,v u,v需要走不同的分支
设 x x x到 u u u需要 i i i步, x x x到 v v v需要 j j j步
当 u > v u>v u>v时答案加上 f [ i ] [ j ] f[i][j] f[i][j]
当 v > u v>u v>u时答案加上 f [ j ] [ i ] f[j][i] f[j][i]
定义 f [ i ] [ j ] f[i][j] f[i][j]表示一条链长 i i i,一条链长 j j j,链 i i i先到的概率
初始化 f [ 0 ] [ j ] = 1 f[0][j]=1 f[0][j]=1
然后 f [ i ] [ j ] = f [ i − 1 ] [ j ] ∗ 1 2 + f [ i ] [ j − 1 ] ∗ 1 2 f[i][j]=f[i-1][j]*\frac{1}{2}+f[i][j-1]*\frac{1}{2} f[i][j]=f[i−1][j]∗21+f[i][j−1]∗21
意思是若第一步选的是长为 i i i的链,那么问题转化为长 i − 1 i-1 i−1和长 j j j链的概率问题
第一步选的是 j j j就转化为长 i i i和长 j − 1 j-1 j−1链的概率问题
这部分代码是
void init()
{
int pro = quick(2,mod-2);
for(int i=1;i<=n;i++) f[0][i] = 1;
for(int i=1;i<=n;i++)
for(int j=1;j+i<=n;j++)
f[i][j] = ( 1ll*f[i-1][j]+f[i][j-1] )*pro%mod;
}
时间复杂度为 O ( n 3 l o g 2 ( n ) ) O(n^3log_2(n)) O(n3log2(n))
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
const int mod = 1e9+7;
const int maxn = 209;
int n,pro;
vector<int>vec[maxn];
int quick(int x,int n)
{
int ans = 1;
for( ; n ; n>>=1,x=1ll*x*x%mod )
if( n&1 ) ans = 1ll*ans*x%mod;
return ans;
}
int f[209][209],sf[209][209];
void init()
{
int pro = quick(2,mod-2);
for(int i=1;i<=n;i++) f[0][i] = 1;
for(int i=1;i<=n;i++)
for(int j=1;j+i<=n;j++)
f[i][j] = ( 1ll*f[i-1][j]+f[i][j-1] )*pro%mod;
}
int fa[maxn][22],deep[maxn];
int lca(int x,int y)
{
if( deep[x]<deep[y] ) swap(x,y);
for(int i=20;i>=0;i--)
if( deep[fa[x][i]]>=deep[y] ) x = fa[x][i];
if( x==y ) return x;
for(int i=20;i>=0;i--)
if( fa[x][i]!=fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int get_dis(int x,int y)
{
int u=lca(x,y);
return deep[x]+deep[y]-2*deep[u];
}
void predfs(int u,int father)
{
fa[u][0] = father; deep[u] = deep[father]+1;
for(int i=1;i<=20;i++)
fa[u][i] = fa[fa[u][i-1]][i-1];
for( auto v:vec[u] )
if( v!=father ) predfs(v,u);
}
int solve()
{
int ans = 0;
for(int u=1;u<=n;u++)
for(int i=u+1;i<=n;i++)
{
int x = lca(u,i), q = get_dis(i,x), w = get_dis(u,x);
if( x==u ) ans = ( ans+(u>i) )%mod;
else if( x==i ) ans = ( ans+(i>u) )%mod;
else
{
if( i>u ) ans = ( ans+f[q][w] )%mod;
else ans = ( ans+f[w][q] )%mod;
}
}
return ans;
}
signed main()
{
cin >> n;
init();
for(int i=1;i<n;i++)
{
int l,r; cin >> l >> r;
vec[l].push_back( r );
vec[r].push_back( l );
}
int res = 0;
for(int i=1;i<=n;i++)
{
predfs(i,0);
res = ( 1ll*res+1ll*solve()*quick(n,mod-2)%mod )%mod;
}
cout << ( res%mod+mod )%mod;
return 0;
}