题解:AT_agc070_b [AGC070B] Odd Namori
更好的阅读体验
太牛了。
一个好图是一个只有奇环的内基环树森林。我们要求的是所有好图中,
但还是不好算。我们把
我们先假设没有不能选树边的限制,考虑在一个点集
首先当
接下来考虑一个非常逆天的双射:将
- 当
1,2 在同一个环上时,效果就是大环被拆成了两个小环,1,2 分别在一个环上。 - 当
1,2 在同一个环上,效果就是1,2 所在两个环合并。
不难看出,偶环数量为奇数的权值和偶环数量为偶数的权值互为相反数!所以当
接下来考虑加上限制后怎么做。连边等价与缩点,我们可以将一个点并到他的父亲上形成若干条链。
但是由于我们上面说了,要产生贡献当且仅当
那么我们考虑实现。我们首先要先将答案加上连边的方案总数
那么这道题就做完了,复杂度
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define N 100006
#define MOD 998244353
using namespace std;
int n,dep[N],t[N],pw[N],ans;
vector<int> G[N];
inline void add(int &x,int y){x+=y,x-=x>=MOD?MOD:0;}
void dfs(int u){for(int v:G[u])t[dep[v]=dep[u]+1]++,dfs(v);}
main()
{
scanf("%lld",&n),pw[0]=1;
for(int i=1;i<N;i++)pw[i]=pw[i-1]*(n-1)%MOD;
for(int i=2,fa;i<=n;i++)
scanf("%lld",&fa),G[fa].push_back(i);
dfs(1),ans=pw[n-1]*n%MOD;
for(int i=n;i;i--)add(t[i],t[i+1]);
for(int i=1;i<=n;i++)add(ans,pw[n-dep[i]-1]);
for(int i=1;i<n;i++)add(ans,t[i]*pw[n-i-1]%MOD*n%MOD);
printf("%lld\n",ans);
return 0;
}