这道题赛时没想到正解,赛后补题wa了三发后,终于找到正解,来写一篇博文。还是考虑逆问题,求有多少个以该点为交点,然后求解即可。
代码:
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std ;
const int N = 2e5 + 10 ;
const int M = 2 * N ;
const int mod = 1e9 + 7 ;
int sz[N] , f[N] ;
int h[N] , e[M] , ne[M] , idx ;
int n , ans = 0 ;
int d[N] ;
void add(int a , int b)
{
e[idx] = b , ne[idx] = h[a] , h[a] = idx ++ ;
}
int qmi(int a , int b)
{
int res = 1 ;
while(b)
{
if(b & 1) res = res * 1ll * a % mod ;
a = a * 1ll * a % mod ;
b >>= 1 ;
}
return res ;
}
int get(int x)
{
return (x % mod + mod) % mod ;
}
int C2(int x)
{
return (x - 1) * 1ll * x % mod * qmi(2 , mod - 2) % mod;
}
void dfs(int u , int v)
{
int res = 0 ;
sz[u] = 1 ;
for(int i = h[u] ; ~i ; i = ne[i])
{
int j = e[i] ;
if(j == v) continue ;
dfs(j , u) ;
sz[u] += sz[j] ;
res = (get(-C2(sz[j])) + res) % mod ;
}
res = (res + C2(sz[u] - 1)) % mod ;
res = (res + sz[u]) % mod ;
ans = (ans + C2(res)) % mod ;
ans = (ans + (n - sz[u]) * 1ll * sz[u] % mod * res % mod) % mod ;
}
int main(void)
{
int T ;
scanf("%d" , &T) ;
while(T --)
{
scanf("%d" , &n) ;
for(int i = 1 ; i <= n ; i ++) h[i] = -1 , sz[i] = d[i] = 0 ;
idx = 0 ;
for(int i = 1 ; i < n ; i ++)
{
int a , b ;
scanf("%d%d" , &a , &b) ;
add(a , b) , add(b , a) ;
d[a] ++ , d[b] ++ ;
}
ans = 0 ;
dfs(1 , 1) ;
printf("%d\n" , (C2(C2(n) + n) + get(-ans)) % mod) ;
}
}