求樹上任意兩點的距離
阿新 • • 發佈:2019-02-06
題意:
有一棵樹,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;
}