HDU 6446 Tree and Permutation(根節點)
阿新 • • 發佈:2018-12-03
這道題我記得當時是在網上找的板子。。。。
http://acm.hdu.edu.cn/showproblem.php?pid=6446
先定義一個數n,n個數有n!種排列方法,然後求兩條邊的權值之和,顯然他是有(n-1)!2種結果,對於兩個相鄰的點來說,他的計算的次數其實是兩個邊的節點所形成的樹的子樹的數量。
#include<iostream> #include<stdio.h> #include<vector> #include<string.h> using namespace std; typedef long long ll; const int maxn = 1e5+10; const int mod = 1e9+7; ll son[maxn],s[maxn]; int u,v,w,n; struct edge{ int v; int w; }; vector<edge>vec[maxn]; void init(){ s[1]=1; for(int i=2;i<maxn;i++){ s[i]=s[i-1]*i%mod; } } ll dfs(int x,int ww,int fat){ ll ret = 0; for(int i=0;i<vec[x].size();i++){ int t=vec[x][i].v; if(t==fat) continue; ret+=dfs(t,vec[x][i].w,x); ret%=mod; } son[fat]+=son[x]+1; ret+=(son[x]+1)*(n-son[x]-1)%mod*ww%mod; ret%=mod; return ret; } int main() { init(); while(cin>>n){ memset(son,0,sizeof(son)); for(int i=0;i<maxn;i++) vec[i].clear(); for(int i=1;i<=n-1;i++){ scanf("%d%d%d",&u,&v,&w); vec[u].push_back(edge{v,w}); vec[v].push_back(edge{u,w}); } printf("%lld\n",dfs(1,0,0)*s[n-1]*2%mod); } return 0; }