1. 程式人生 > >(1009) HDU 6446 Tree and Permutation(規律+樹上各個點的距離和)

(1009) HDU 6446 Tree and Permutation(規律+樹上各個點的距離和)

isp font ide display clu open 距離 main blank

題意:

給一棵N個點的樹,對應於一個長為N的全排列,對於排列的每個相鄰數字a和b,他們的貢獻是對應樹上頂點a和b的路徑長,求所有排列的貢獻和。

分析:

經過簡單的分析可以得知,全部的貢獻其實相當與(這顆樹上各個點的距離之和)*jichen(n-1) *2;

不相信可以舉個簡單的例子,或者用計算機打表可以知道;

那麽如何求樹上各個點的距離和呢?

可以參考這個博客:https://www.cnblogs.com/shuaihui520/p/9537214.html ;

那下面的問題就相當的簡單了;

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
const
int maxn = 100001; const int mod = 1e9+7; #define ll long long ll sum[maxn]; int n; ll dp[maxn]; struct no { int v,w; }t1,t2; vector<no>tree[maxn]; void dfs(int cur, int father) { sum[cur] = 1; for(int i = 0; i < tree[cur].size(); i++) { int son = tree[cur][i].v; ll len
= tree[cur][i].w; if(father == son) continue; dfs(son, cur); sum[cur] = (sum[cur]+sum[son])%mod; dp[cur] = ((dp[cur]+dp[son])%mod + (n-sum[son])*sum[son]%mod * len%mod)%mod; } } ll jichen(int n) { ll sum=1; while(1) { if(n==1)
break; sum=(sum*n)%mod; n--; } return sum; } int main( ) { while(scanf("%d",&n)!=EOF) { for(int i=0 ; i<=n ; i++) tree[i].clear(); memset(sum,0,sizeof(sum)); memset(dp,0,sizeof(dp)); for(int i = 0 ; i<n-1 ; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); u--;v--; tree[u].push_back(no{v,w}); tree[v].push_back(no{u,w}); } dfs(0,-1); printf("%lld\n",(dp[0]*jichen(n-1))%mod*2%mod); } return 0; }
View Code

(1009) HDU 6446 Tree and Permutation(規律+樹上各個點的距離和)