Tree and Permutation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 194 Accepted Submission(s): 65
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
[题意]
求 n 得 全排列序列: 从1 - n 点 最短路的和,
解释样例:
全排列为 :
1 2 3: 1到2 + 2到3 = 2
1 3 2: 1到3 + 3到2 = 3
2 1 3: 2到1 + 1到3 = 3
2 3 1: 2到3 + 3到1 = 3
3 1 2: 3到1 + 1到2 = 3
3 2 1: 3到2+ 2到1 = 2
sum = 3*4+2*2 = 16;
[思路]
转化 全排列 1e5是不现实的, 通过样例可以发现: 出现许多重复项;
123 的全排列中 重复计算 1-2 , 1-3, 2-3 并且 每个都重复 n!*(n-1) / n*(n-1)/2 = 2*(n-1)!
n*(n-1)/2 是 1-2 , 1-3, 2-3 的个数.
然后我们 在根据这个建的图:
例如 下面这个图;
以 3-5 为边 , 统计两个端点 两边的数, x 和 y 那么, 边 3-5 一次 被用到的次数 就是 x*y 次
对总的贡献就是 2*(n-1)!*(x*y)*Val
然后我们 DFS统计点数, 维护 答案
[代码]
#include <bits/stdc++.h>
#include <stdio.h>
typedef long long ll;
using namespace std;
const int mod=1e9+7;
const int maxn = 1e5+10;
int head[2*maxn],node[maxn],vis[maxn],n,num;
ll fac[maxn];
struct point{
int to;
int next;
ll val;
}pt[2*maxn];
int q;
ll sum;
void init()
{
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
memset(node,0,sizeof(node));
q=0;
}
void add(int u,int v,ll val)
{
pt[q].next=head[u];
pt[q].to=v;
pt[q].val=val;
head[u]=q++;
}
int dfs(int st)
{
for (int i=head[st];i!=-1;i=pt[i].next)
{
int to=pt[i].to;
if (!vis[to])
{
vis[to]=1;
node[st]+=dfs(to);
}
}
if (node[st]==0)
return node[st]=1;
node[st]+=1;
return node[st];
}
void dfs1(int st)
{
for (int i=head[st];i!=-1;i=pt[i].next)
{
int to=pt[i].to;
if (!vis[to])
{
vis[to]=1;
ll minn=min(node[st],node[to]);
sum=1ll*(sum+minn*(n-minn)%mod*pt[i].val%mod*num%mod)%mod;
dfs1(to);
}
}
}
int main(int argc, char const *argv[])
{
fac[1]=1;
for (int i=2;i<=maxn;i++)
fac[i]=fac[i-1]*i%mod;
int u,v;
ll val;
while (scanf("%d",&n)!=EOF)
{
init();
sum=0;
for (int i=1;i<n;i++)
{
scanf("%d%d%lld",&u,&v,&val);
add(u,v,val);
add(v,u,val);
}
num=(fac[n-1]*2)%mod;
vis[1]=1;
dfs(1);
// for (int i=1;i<=n;i++)
// cout<<node[i]<<"****"<<endl;
memset(vis,0,sizeof(vis));
vis[1]=1;
dfs1(1);
printf("%lld\n",sum);
}
return 0;
}