Codeforces Round #564 (Div. 2) D. Nauuo and Circle
題意
給你一棵樹,問把這棵樹放在一個圓上,保證任意兩邊不相交,而且從任意一點順時針繞圓周的下標序列不同就算不同的放法,求方案數。
做法
首先考慮樹形dp,由於在圓周上,一個子樹肯定是一段連續的區間,那麼也就是對於以u爲根的來說,他的幾個兒子之間是可以隨意交換位置的,而且保證不會相交,所以加上u指向父親那條邊,所有邊都可以任意交換位置,也就是u這個點度數的階乘種交換位置,我們再乘上每棵子樹的答案樹,由於我們固定以1爲根,而1又有n個位置可以選擇,所以最後dp[1]*n就是答案。注意根結點沒有父親,所以只有兒子之間任意交換即可。
代碼
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
const int Mod = 998244353;
const int maxn = 2e5+10;
ll dp[maxn];
vector<int> G[maxn];
ll t[maxn];
void dfs(int rt,int fa)
{
dp[rt]=1;
for(int i=0;i<G[rt].size();i++)
{
int to=G[rt][i];
if(to==fa) continue;
dfs(to,rt);
dp[rt]=dp[rt]*dp[to]%Mod;
}
dp[rt]=dp[rt]*t[(int)G[rt].size()]%Mod;
}
int main()
{
int n;
scanf("%d",&n);
t[0]=1;
for(int i=1;i<=n;i++) t[i]=t[i-1]*i%Mod;
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,-1);
printf("%lld\n",dp[1]*n%Mod);
return 0;
}