链接:https://ac.nowcoder.com/acm/contest/18072/E
题目:给你一棵n个节点的带标号无根树。每次,你可以选择一个度数为1的节点并将它从树上移除。问总共有多少种不同的方式能将这棵树删到只剩 1 个点。两种方式不同当且仅当至少有一步被删除的节点不同。
思路:首先我们把他看成有根树来求解,一般我们以1为根,也就是说1结点是最后才去除的,我们以dp【i】来表示去除i子树有多少种方式,dp[i]= (v是i的儿子);每次统计完答案以后都要sizei-sizev,很容易想到这个跟减的顺序是没有关系的。
现在我们统计完了有根树的值,现在可以考虑来换根了,我们考虑从x->y,从x根转化到y根,首先我们考虑一下回退,在y根中, ,;
根据这两条公式已经可以进行换根,我们还可以化简,把dp1[y]约掉;
代码:
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cstdlib>
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define re register
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(a) ((a)&-(a))
#define ios std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
#define fi first
#define rep(i,n) for(int i=0;(i)<(n);i++)
#define rep1(i,n) for(int i=1;(i)<=(n);i++)
#define se second
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define ac cout<<ans<<"\n"
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
int dx[4]= {-1,1,0,0},dy[4]= {0,0,1,-1};
const ll mod=998244353;
const ll N =1e6+10;
const double eps = 1e-4;
//const double pi=acos(-1);
int n;
vector<int> g[N];
ll f[N],invf[N],inv[N];
ll dp[N];
ll son[N];
ll ans;
int c(int x,int y){return (((f[x]*invf[x-y])%mod)*invf[y])%mod;
}
void dfs(int u,int p){son[u]=1;dp[u]=1;for(int v:g[u]){if(v==p) continue;dfs(v,u);son[u]+=son[v];}int s=son[u]-1;for(int v:g[u]){if(v==p) continue;dp[u]=(dp[u]*(c(s,son[v])*dp[v]%mod))%mod;s-=son[v];}//cout<<u<<" "<<dp[u]<<endl;
}
void DP(int u,int p){ans=(ans+dp[u])%mod;for(int v:g[u]){if(v==p) continue;dp[v]=dp[u]*invf[son[v]-1]%mod*f[son[v]]%mod;dp[v]=dp[v]*invf[n-son[v]]%mod;dp[v]=dp[v]*f[n-1-son[v]]%mod;DP(v,u);}
}
void sovle(){cin>>n;f[0]=f[1]=invf[0]=invf[1]=inv[1]=1;for(int i=2;i<=n;i++){f[i]=(f[i-1]*i)%mod;inv[i]=(mod-mod/i)*inv[mod%i]%mod;invf[i]=invf[i-1]*inv[i]%mod;}for(int i=1;i<n;i++){int x,y;cin>>x>>y;g[x].push_back(y);g[y].push_back(x);}dfs(1,0);//cout<<dp[1]<<endl;DP(1,0);cout<<ans;
}
int main()
{
#ifdef LOCALfreopen("in.txt", "r", stdin);
#elseint t=1;// cin>>t;while(t--) sovle();
#endif // LOCALreturn 0;
}