树上边分治-求任意两点路径的总和

传送门http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1009&cid=812

经过组合数学推导可得     题目要求2*(n-1)!*树上路径总和

路径总和可以通过边dfs边计算

每一条边的贡献为 siz*(n-siz)次 siz为子树大小

/**
    Copyright(c)
    All rights reserved.
    Author : @klay
    Date : 2018-08-28-20.16.35
    Description : 树上任意两点路径总和
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<bitset>
#include<utility>
#include<functional>
#include<iomanip>
#include<sstream>
#include<ctime>
#include<cassert>
#define A first
#define B second
#define mp make_pair
#define pb push_back
#define pw(x) (1ll << (x))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define rep(i,l,r) for(int i=(l);i<(r);i++)
#define per(i,r,l) for(int i=(r);i>=(l);i--)
#define FOR(i,l,r) for(int i=(l);i<=(r);i++)
#define eps 1e-9
#define PIE acos(-1)
#define cl(a,b) memset(a,b,sizeof(a))
#define fastio ios::sync_with_stdio(false);cin.tie(0);
#define lson l , mid , ls
#define rson mid + 1 , r , rs
#define ls (rt<1)
#define rs (ls|1)
#define INF 0x3f3f3f3f
#define lowbit(x) (x&(-x))
#define sqr(a) a*a
#define ll long long
#define vi vector<int>
#define pii pair<int, int>
#define dd(x) cout << #x << " = " << (x) << ", "
#define de(x) cout << #x << " = " << (x) << "\n"
#define endl "\n"
using namespace std;
//**********************************
const int maxn=1e5+7;
const int mod=1e9+7;
struct Edge
{
    int to,dist,next;
}edge[maxn];
int tot,n,m,head[maxn],fac[maxn+7]={1};
ll ans;
//**********************************
void Init()
{
    tot=0;
    ans=0;
    cl(head,-1);
}
void getfac()
{
    FOR(i,1,maxn)fac[i]=fac[i-1]*i%mod;
}
void add_edge(int from,int to,int dist)
{
    edge[tot].to=to;
    edge[tot].dist=dist;
    edge[tot].next=head[from];
    head[from]=tot++;
}
int dfs(int u,int fa)
{
    int size=1;
    for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].to;
        int siz=dfs(v,u);
        ll tmp=siz%mod*(n-siz)%mod*2%mod*(fac[n-1])%mod*edge[i].dist%mod;
        ans=(ans+tmp)%mod;
        size+=siz;
    }
    return size;
}
//**********************************
int main()
{
    getfac();
    while(~scanf("%d",&n)){
        Init();
        int u,v,w;
        rep(i,0,n-1)scanf("%d%d%d",&u,&v,&w),add_edge(u,v,w),add_edge(v,u,w);
        dfs(1,-1);
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/klaycf/p/9550841.html