这道题我记得当时是在网上找的板子。。。。
http://acm.hdu.edu.cn/showproblem.php?pid=6446
先定义一个数n,n个数有n!种排列方法,然后求两条边的权值之和,显然他是有(n-1)!2种结果,对于两个相邻的点来说,他的计算的次数其实是两个边的节点所形成的树的子树的数量。
#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
const int mod = 1e9+7;
ll son[maxn],s[maxn];
int u,v,w,n;
struct edge{
int v;
int w;
};
vector<edge>vec[maxn];
void init(){
s[1]=1;
for(int i=2;i<maxn;i++){
s[i]=s[i-1]*i%mod;
}
}
ll dfs(int x,int ww,int fat){
ll ret = 0;
for(int i=0;i<vec[x].size();i++){
int t=vec[x][i].v;
if(t==fat)
continue;
ret+=dfs(t,vec[x][i].w,x);
ret%=mod;
}
son[fat]+=son[x]+1;
ret+=(son[x]+1)*(n-son[x]-1)%mod*ww%mod;
ret%=mod;
return ret;
}
int main()
{
init();
while(cin>>n){
memset(son,0,sizeof(son));
for(int i=0;i<maxn;i++)
vec[i].clear();
for(int i=1;i<=n-1;i++){
scanf("%d%d%d",&u,&v,&w);
vec[u].push_back(edge{v,w});
vec[v].push_back(edge{u,w});
}
printf("%lld\n",dfs(1,0,0)*s[n-1]*2%mod);
}
return 0;
}