Tree and PermutationTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 541 Accepted Submission(s): 182 Problem Description There are N vertices connected by N−1 edges, each edge has its own length.
Input There are 10 test cases at most.
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
Recommend chendu | We have carefully selected several similar problems for you: 6447 6446 6445 6444 6443 |
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long
const int maxn =1e5+5;
const int mod=1e9+7;
ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
ll powmod(ll x,ll y){ll t;for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod;return t;}
/*
题目大意:题目叙述上饶了点弯子,
对于一个排列的权重,代表从a1走到a2,a2走到a3,,,这样走下去的权重和,就是一个排列的权重,
然后求全排列的权重和。。
数学转换下即可:对于任意的xy,其在全排列中相邻的组合数是(n-1)!*2。
这样题目意思就明了了,求一棵树中任意两点距离和,边上有权重。
贡献思维,看每条边对答案的贡献。
一条边被n1*n2次走过,n1,n2分别为边两边的子树的节点数。
树形DP去解析,有三个状态,子节点数,子节点到根节点距离和,子树中任意两点距离和。
三个状态具体如何转移详见代码,状态和顺序绝对不能错。
(我这个好像写烦了,,其实就是简单的对每个边求其贡献即可,分开的两颗子树节点乘积*权重。。。)
*/
struct node///链式前向星板子
{
int nxt;
int e;
ll w;
node(int x=0,int y=0,ll z=0)
{
e=x;
nxt=y;
w=z;
}
};
node edge[maxn<<1];
int head[maxn],tot=0;
void init(){memset(head,-1,sizeof(head));tot=0;}
void add(int a,int b,ll c){edge[tot]=node(b,head[a],c);head[a]=tot++;}
ll n,dp[maxn][3];///0代表子树的节点数,1代表子树中所有点到根节点的路径之和,2代表子树中任意点对距离和。
void dfs(int u,int p)
{
if(head[u]==-1) {dp[u][0]=1;return ;}
for(int i=head[u];~i;i=edge[i].nxt)
{
int v=edge[i].e;
if(v==p) continue;
dfs(v,u);
(dp[u][2]+=dp[v][2]+dp[v][1]*dp[u][0]%mod+dp[v][0]*dp[u][1]%mod+dp[u][0]*dp[v][0]%mod*edge[i].w%mod)%=mod;///又是一个线性的动态规划
(dp[u][1]+=dp[v][1]%mod+dp[v][0]*edge[i].w%mod)%=mod;
(dp[u][0]+=dp[v][0])%=mod;///子树的顶点数
}
dp[u][0]++;
(dp[u][2]+=dp[u][1])%=mod;///
}
int x,y;
ll fac[maxn],z;
int main()
{
fac[0]=1;for(int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod;
while(~scanf("%lld",&n))
{
init();
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
memset(dp,0,sizeof(dp));
dfs(1,-1);
ll ans=dp[1][2]*fac[n-1]%mod*2%mod;
printf("%lld\n",ans);
}
return 0;
}
/*
4
1 3 1
1 2 1
1 4 1
*/