【Codeforces Round #564 (Div. 2) D. Nauuo and Circle】

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章