【2018 CCPC网络赛】1009 - 树

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6446

 

题目给出的数据为一棵树,dfs扫描每条边,假设去掉某条边,则左边 x 个点,右边 n-x 个点,则经过该条边共有 x*(n-x) 种组合,又因为 1~n 全排列有 n! 种,故 a~b,包含 b~a 这条边的贡献为 (n-x)*x*2*(n-1)!*w;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 using namespace std;
 5 
 6 #define LL long long
 7 const int MOD = 1e9+7;
 8 const int N = 1e5+5;
 9 struct EDGE {
10     LL to, length;
11 };
12 vector<EDGE> edge[N];
13 LL n, factorial[N], lchild[N], w[N];
14 
15 int dfs(int k, int pre) {
16     int size = edge[k].size(), ans=1;
17     for(int i=0; i<size; i++) {
18         if(edge[k][i].to == pre)
19             w[k] = edge[k][i].length;
20         else
21             ans += dfs(edge[k][i].to, k);
22     }
23     return lchild[k] = ans;
24 }
25 
26 int main()
27 {
28     factorial[1] = 1;
29     for(int i=2; i<N; i++)
30         factorial[i] = factorial[i-1]*i%MOD;
31     
32     while(~scanf("%d",&n))
33     {
34         LL  ans=0;
35         for(int i=1; i<=n; i++) {
36             edge[i].clear();
37         }
38         for(int x,y,v,i=1; i<n; i++) {
39             scanf("%d%d%d", &x, &y, &v);
40             edge[x].push_back({y,v});
41             edge[y].push_back({x,v});
42         }
43         
44         dfs(1, -1);
45         for(int i=2; i<=n; i++) {
46             LL tmp=1;
47             tmp = lchild[i]*(n-lchild[i])%MOD;
48             tmp = 2*factorial[n-1]%MOD*w[i]%MOD*tmp%MOD;
49             ans = (ans+tmp)%MOD;
50         }
51         cout<<ans<<endl;
52     }
53     return 0;
54 }

 

posted @ 2018-08-28 16:05  liubilan  阅读(175)  评论(0编辑  收藏  举报