题解:
支配树裸题了。。
写这篇博客只是为了提供一份支配树的代码。。
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
inline void W(int x){
static int buf[50];
if(!x){putchar('0');return;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0])putchar(buf[buf[0]--]+'0');
}
inline void gmin(int &x,int y){(x>y)?(x=y):0;}
const int N=1e5+50;
int rt,n,sdom[N],idom[N],id[N],dfn[N],mnsd[N],tot,anc[N],fa[N];
vector<int>pre[N],buc[N],edge[N];
struct DominatorTree{
int sze[N],v[N],nt[N],g[N],ec;
inline void add(int x,int y){nt[++ec]=g[x];g[x]=ec;v[ec]=y;}
inline void dfs(int x){
sze[x]=1;
for(int j=g[x];j;j=nt[j])dfs(v[j]),sze[x]+=sze[v[j]];
}
}g;
inline void dfs(int x,int f=0){
dfn[x]=++tot;id[tot]=x;fa[x]=f;
sdom[x]=mnsd[x]=anc[x]=x;
for(int e=edge[x].size()-1;e>=0;e--){
int v=edge[x][e];
if(dfn[v])continue;
dfs(v,x);
}
}
inline void getanc(int p){
if(anc[p]!=p)getanc(anc[p]);
if(dfn[sdom[mnsd[anc[p]]]]<dfn[sdom[mnsd[p]]])mnsd[p]=mnsd[anc[p]];
anc[p]=anc[anc[p]];
}
inline int eval(int p){ //获取到根节点路径上sdom最小的点
getanc(p);
return mnsd[p];
}
int main(){
n=rd();rt=n+1;
for(int i=1;i<=n;i++){
int cnt=0,x=rd();
while(x){
pre[i].push_back(x);
edge[x].push_back(i);
++cnt;x=rd();
}
if(!cnt){
pre[i].push_back(rt);
edge[rt].push_back(i);
}
}
dfs(rt);fa[rt]=rt;
for(int i=tot;i>=1;i--){
int u=id[i];
for(int j=pre[u].size()-1;j>=0;j--){
int t=eval(pre[u][j]);
if(dfn[sdom[t]]<dfn[sdom[u]])sdom[u]=sdom[t];
}
anc[u]=fa[u];int f=fa[u];
buc[sdom[u]].push_back(u);
for(int j=buc[f].size()-1;j>=0;j--){ //此时该节点所有子树以父节点为半支配点的点路径全部已经处理出
int v=buc[f][j];int t=eval(v);
if(dfn[sdom[t]]<dfn[sdom[v]])idom[v]=t;
else idom[v]=sdom[v];
}
buc[f].clear();
}
for(int i=2;i<=tot;i++){
int u=id[i];
if(idom[u]!=sdom[u])idom[u]=idom[idom[u]];
g.add(idom[u],u);
}
g.dfs(id[1]);
for(int i=1;i<=n;i++){
W(g.sze[i]-1);putchar('\n');
}
}