终于理解了...
希望写给小伙伴们,希望大伙可以理解。
先确定贪心规则,即当最大子树不超过根子树减一的一半时,内部节点可以完全匹配。否则,可以先拿其他子树节点与最大子树内部节点匹配,子树内部再进行匹配。啥你说子树内部不够匹配怎么办?可以这么想,你这样都到匹配上限了,已经完全可以达到最优秀情况,取max即可。
设f[u]为以u为根的子树的最大匹配数。转移方程略。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) using namespace std; const int N=2e5+5; int siz[N],n; vector<int> son[N]; int f[N]; void find_siz(int u){ siz[u]=1; for(int& v:son[u]){ find_siz(v); siz[u]+=siz[v]; } } void dfs(int u){ int mx=-1; for(int v:son[u]){ if(mx==-1||siz[v]>siz[mx]) mx=v; dfs(v); } if(mx==-1) { f[u]=0; return; } int res=siz[u]-siz[mx]-1; if(res>=siz[mx]){ f[u]=(siz[u]-1)/2; return; } f[u]=min(res+f[mx],(siz[u]-1)/2); } void solve(){ fill(f,f+N,0); fill(siz,siz+N,0); cin>>n; rep(i,0,n) son[i].clear(); rep(i,2,n){ int x;cin>>x; son[x].push_back(i); } find_siz(1); dfs(1); cout<<f[1]<<'\n'; } signed main(){ int T; cin>>T; while(T--) solve(); }
标签:CF1914F,匹配,int,siz,Programming,Competition,son,子树,mx From: https://www.cnblogs.com/Kopicy/p/17929375.html