1. 程式人生 > >求樹上任意兩點的距離

求樹上任意兩點的距離

題意:
有一棵樹,N個節點,N-1條邊。節點有N!種全排列,那麼就有N!棵樹,求這N!,每棵樹的距離總和是樹上任意兩點距離和,求這N!棵樹的距離。

思路:
對任意一條距離分析,發現任意一條路徑會被使用(N-1)!
所以答案就是求出一個樹任意兩點的距離和,最後乘以(N-1)!,因為1->2是一條路徑,2->1也是一條路勁,最後再乘以2

#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; typedef unsigned int uint; typedef pair<int, int> PII; const int INF = 0x3f3f3f3f; const double eps = 1e-6; const int MAXN = 100000 + 5; const int MOD=1e9+7; struct TNode { int
v, w; TNode() {} TNode(int v, int w) : v(v), w(w) {} }; int T, N; vector<TNode> G[MAXN]; LL sum[MAXN]; LL ans; void init() { memset(sum, 0, sizeof(sum)); for (int i = 0; i < N; i++) G[i].clear(); } void dfs(int root, int father) { sum[root] = 1; for (int i = 0; i < G[root].size(); i++) { TNode& e = G[root][i]; int
son = e.v; if (son == father) continue; dfs(son, root); sum[root] =(sum[root]+ sum[son])%MOD; ans =(ans+ (LL)(sum[son]%MOD * (N - sum[son]))%MOD * e.w%MOD)%MOD; } } LL F[MAXN]; int main() { F[1]=1; for(int i=2;i<=100000;i++) { F[i]=F[i-1]%MOD*i%MOD; } while(scanf("%d", &N)!=EOF) { init(); int u, v, w; for (int i = 0; i < N - 1; i++) { scanf("%d %d %d", &u, &v, &w); G[u-1].push_back(TNode(v-1, w)); G[v-1].push_back(TNode(u-1, w)); } ans = 0; dfs(0, -1); printf("%lld\n", (LL)(ans%MOD*F[N-1]%MOD*2)%MOD); }這裡寫程式碼片 return 0; }