@2018中国大学生程序设计竞赛 - 网络选拔赛:1009 Tree and Permutation(DFS)

版权声明:岂曰无衣,与子同袍 https://blog.csdn.net/sizaif/article/details/82054789

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;
}

猜你喜欢

转载自blog.csdn.net/sizaif/article/details/82054789
今日推荐