CF1032F Vasya and Maximum Matching 题解
重点在于转化“最大匹配唯一”的限制。发现它等价于树是孤点或最大匹配是完美匹配。
显然,最大匹配若不完美则容易调整出多个最大匹配。若最大匹配完美,考虑反证法,假设存在多个完美匹配,对比任意一对都能找到环,矛盾。
然后设 \(f_{u,0/1/2}\) 分别为 \(u\) 和父亲匹配、和儿子匹配、作为孤点时 \(u\) 子树的删边方案数。
设 \(u\) 的儿子集合为 \(son_u\)。转移方程如下。
\[f_{u,0}=\prod_{v\in son_u}\left(2f_{v,1}+f_{v,2}\right)
\]
\[f_{u,1}=\left(\prod_{v\in son_u}\left(2f_{v,1}+f_{v,2}\right)\right)\cdot\left(\sum_{v\in sum_u}\frac{f_{v,0}}{2f_{v,1}+f_{v,2}}\right)
\]
\[f_{u,2}=\prod_{v\in son_u}\left(f_{v,1}+f_{v,2}\right)
\]
其中 \(f_{u,1}\) 的计算可以使用前缀和技巧避免求逆元,具体实现见代码。时间复杂度 \(O(n)\)。
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i(a);i<b;++i)
#define rept(i,a,b) for(int i(a);i<=b;++i)
#define eb emplace_back
#define int long long
using namespace std;
constexpr int P=998244353,N=3e5+5;
int n,u,v,f[N][3];
vector<int> g[N];
// f[i][0]:i的子树,i和fa[i]匹配的方案数
// f[i][1]:i的子树,i和i的一个儿子匹配的方案数
// f[i][2]:i的子树,i孤立的方案数
void dfs(int u,int pre){
f[u][0]=f[u][2]=1;
f[u][1]=0;
int t=1;
for(int v:g[u]){
if(v==pre) continue;
dfs(v,u);
(f[u][0]*=f[v][1]*2+f[v][2])%=P;
f[u][1]=(f[u][1]*(f[v][1]*2+f[v][2])+t*f[v][0])%P;
(t*=f[v][1]*2+f[v][2])%=P;
(f[u][2]*=f[v][1]+f[v][2])%=P;
}
}
signed main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n;
rep(i,1,n){
cin>>u>>v;
g[u].eb(v),g[v].eb(u);
}
dfs(1,0);
cout<<(f[1][1]+f[1][2])%P;
cerr<<1000.0*clock()/CLOCKS_PER_SEC<<"ms"<<endl;
return 0;
}

浙公网安备 33010602011771号