第十九届浙大城市学院程序设计竞赛EDisjoint Path On Tree题解

这道题赛时没想到正解,赛后补题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) ;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值