Tree and Permutation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1414 Accepted Submission(s): 528
Problem Description
There are N vertices connected by N−1 edges, each edge has its own length.
The set { 1,2,3,…,N } contains a total of N! unique permutations, let’s say the i-th permutation is Pi and Pi,j is its j-th number.
For the i-th permutation, it can be a traverse sequence of the tree with N vertices, which means we can go from the Pi,1-th vertex to the Pi,2-th vertex by the shortest path, then go to the Pi,3-th vertex ( also by the shortest path ) , and so on. Finally we’ll reach the Pi,N-th vertex, let’s define the total distance of this route as D(Pi) , so please calculate the sum of D(Pi) for all N! permutations.
Input
There are 10 test cases at most.
The first line of each test case contains one integer N ( 1≤N≤105 ) .
For the next N−1 lines, each line contains three integer X, Y and L, which means there is an edge between X-th vertex and Y-th of length L ( 1≤X,Y≤N,1≤L≤109 ) .
Output
For each test case, print the answer module 109+7 in one line.
Sample Input
3
1 2 1
2 3 1
3
1 2 1
1 3 2
Sample Output
16
24
Source
解析:考虑u,v两个点路径对答案的贡献次数,因为是全排列,那么u,v可以放在1,2位置,2.3位置。。。有(n-1)个位置,在颠倒一下顺序就是(n-1)*2,然后其他n-2个点可以随意排,也就是(n-2)!,所以任意一条边的贡献次数就是2*(n-1)!
所以问题就变为求任意两点的路径和,在这个问题上每条边的贡献就是用这条把树节点分为两个部分,那么这个边的贡献次数就是这两部分点的乘积了,这个用dfs求树大小就可以了。dp[i]表示第i到n点总边的贡献次数,i表示第几个点,比如一条边的两端节点数x+y=n,dp[i]+=dp[(i的邻点)]+x*(n-x)*w,则ans=dp[1]*2*(n-1)!
#include<bits/stdc++.h>
using namespace std;
#define e exp(1)
#define pi acos(-1)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a))
int gcd(int a,int b){return b?gcd(b,a%b):a;}
const int maxn=1e5+5;
struct node{
int v,w;
};
ll f[maxn],dp[maxn],sum[maxn];
int n;
vector<node> ve[maxn];
void dfs(int x,int f)
{
sum[x]=1;
for(int i=0; i<ve[x].size(); i++)
{
int a=ve[x][i].v;
int b=ve[x][i].w;
if(a==f)continue;
dfs(a,x);
sum[x]+=sum[a];
dp[x]=(dp[x]+dp[a]+b*sum[a]%mod*(n-sum[a])%mod)%mod;
}
}
int main()
{
f[0]=1;
for(int i=1; i<maxn; i++)f[i]=f[i-1]*i%mod;
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)ve[i].clear();
mem(dp,0);
mem(sum,0);
for(int i=1; i<n; i++)
{
int x,y,vv;scanf("%d%d%d",&x,&y,&vv);
node a,b;
a.v=y,a.w=vv;
ve[x].push_back(a);
b.v=x,b.w=vv;
ve[y].push_back(b);
}
dfs(1,-1);
//printf("%lld***\n",dp[1]);
ll ans=(dp[1]*f[n-1]%mod*2)%mod;
printf("%lld\n",ans);
}
return 0;
}