1. 程式人生 > >2018中國大學生程序設計競賽 - 網絡選拔賽 1009 - Tree and Permutation 【dfs+樹上兩點距離和】

2018中國大學生程序設計競賽 - 網絡選拔賽 1009 - Tree and Permutation 【dfs+樹上兩點距離和】

根據 print hide 學生 通過 ssi spa memset mod

Tree and Permutation

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 619 Accepted Submission(s): 214

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 ( 1N105 ) .
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 ( 1X,YN,1L109 ) .

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 2018中國大學生程序設計競賽 - 網絡選拔賽

大概題意:

給一棵N個節點的樹, 求按N個節點全排列的順序走一遍這棵樹所得的路徑貢獻和。

解題思路:

對於所有按照全排列走過的路徑,打表會發現,每兩點之間的距離都出現了 (N-1)!次,所以我們只需要求出 所有兩點之間的距離之和就可以解得最後的答案了。

也就是說我們只需要求出 ∑dis(i, j) 最後 ∑dis(i, j) * (N-1)! 就是答案了。

∑dis(i, j) 的求法:

我們可以根據當前節點 root 和 它的父節點 fa 的邊 v 把一棵樹分成兩部分, 一部分是 以 fa 為根節點的子樹,一部分是以 root 為根節點的子樹(即除去這課子樹是另一部分)。

如果我們已經預先知道了 fa 到 這棵樹每個節點的距離和 sum_dis[ fa ], 以及以 root 為根節點的子樹的大小t_size[ root ] ,那麽 節點 root 到樹上其他節點的距離和我們可以通過 sum_dis[ fa ]轉化而來;

因為sum_dis[fa] 減去 v 對上面所分成的樹的兩部分的影響剩下的就是sum_dis[root] 即sum_dis[root] = sum_dis[fa] - (N-t_size[root])*v - t_size[root]*v ;

因此,我們第一步dfs把 1 到各個節點的距離和求出來,第二步通過對 1 的距離和轉換 把其他節點的距離和求出來,最後所有距離和求和得出答案。

AC code:

技術分享圖片
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cmath>
 5 #define ll long long int
 6 #define mod 1000000007
 7 #define INF 0x3f3f3f3f
 8 using namespace std;
 9 
10 const int MAXN = 1e5+10;
11 struct date{
12     int v, next, len;
13 }node[MAXN<<1];
14 ll sum_dis[MAXN];
15 int t_size[MAXN];
16 int head[MAXN], cnt;
17 int N;
18 
19 void init()
20 {
21     memset(head, -1, sizeof(head));
22     cnt = 0 ;
23     memset(sum_dis, 0, sizeof(sum_dis));
24     memset(t_size, 0, sizeof(t_size));
25 }
26 void add(int from, int to, int weight)
27 {
28      node[++cnt].next = head[from];
29      head[from] = cnt;
30      node[cnt].v = to;
31      node[cnt].len = weight;
32 }
33 void dfs(int root, int fa, ll dis)
34 {
35     sum_dis[1] = (sum_dis[1]%mod+dis%mod)%mod;
36     t_size[root] = 1;
37     for(int x = head[root]; x != -1; x =node[x].next)
38     {
39         if(node[x].v != fa)
40         {
41             dfs(node[x].v, root, (dis+node[x].len)%mod);
42             t_size[root]+=t_size[node[x].v];
43         }
44     }
45 }
46 void trans(int root, int fa)
47 {
48     int vv;
49     for(int i = head[root]; i != -1; i= node[i].next)
50     {
51         vv = node[i].v;
52         if(node[i].v != fa){
53             sum_dis[vv] = (sum_dis[root]%mod+((1ll*(N-2*t_size[vv])*node[i].len)%mod)%mod)%mod;
54             if(sum_dis[vv] < 0) sum_dis[vv] += mod;
55             trans(vv, root);
56         }
57     }
58 }
59 int main()
60 {
61     int f, t, w;
62     while(~scanf("%d", &N))
63     {
64         init();
65         for(int i = 1; i < N; i++)
66         {
67             scanf("%d%d%d", &f, &t, &w);
68             add(f, t, w);
69             add(t, f, w);
70         }
71         dfs(1, 0, 0);
72         trans(1, 0);
73         ll P = 1, ans = 0;
74         for(int i = 1; i < N; i++)
75             P = 1ll*P*i%mod;
76         for(int i = 1; i <= N; i++)
77             ans = (ans + sum_dis[i])%mod;
78         ans = ans*P%mod;
79         printf("%lld\n", ans);
80     }
81     return 0;
82 }
View Code

2018中國大學生程序設計競賽 - 網絡選拔賽 1009 - Tree and Permutation 【dfs+樹上兩點距離和】