支配树,用的是求出半支配点后转为DAG的做法。半支配点都是对的,但只有40分,WA的点比正解大了一点。求大佬帮忙看看吧QAQ
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define I inline
#define nnq nanachi
#define inf 1919810
#define int long long
using namespace std;
const int N = 200010;
vector<int> mkq[N],mkrq[N],q[N],rq[N],g[N],rg[N],tr[N];
int n,m,cnt,tpcnt,fa[N],f[N],du[N],id[N],ans[N],dfn[N],dep[N],siz[N],tpn[N],tpid[N],mina[N],semi[N],ioom[N],bz[N][21];
queue<int> ranran;
int find(int x) {
if(x==fa[x]) return x;
int mk=fa[x]; fa[x]=find(fa[x]);
if(dfn[semi[mina[mk]]]<dfn[semi[mina[x]]]) mina[x]=mina[mk];
return fa[x];
}
void dfs(int x,int nfa) {
dfn[x]=++cnt; id[cnt]=x; f[x]=nfa;
if(nfa!=0) g[nfa].push_back(x),du[x]++;
for(int i=0;i<q[x].size();++i) {
int to=q[x][i];
if(dfn[to]) continue;
dfs(to,x);
}
}
I void builddag() {
for(int i=1;i<=n;++i) mkq[i].clear(),mkrq[i].clear();
for(int i=1;i<=n;++i) {
if(semi[i]==i) continue;
g[semi[i]].push_back(i),du[i]++;
rg[i].push_back(semi[i]);
}
}
I void topusort() {
for(int i=1;i<=n;++i) {
if(du[i]) continue;
g[0].push_back(i);
rg[i].push_back(0);
du[i]++;
}
ranran.push(0);
while(!ranran.empty()) {
int k=ranran.front(); ranran.pop();
tpid[++tpcnt]=k;
for(int i=0;i<g[k].size();++i) {
int to=g[k][i];
du[to]--;
if(!du[to]) ranran.push(to);
}
}
}
int qlca(int x,int y) {
if(dep[x]>dep[y]) swap(x,y) ;
for(int i=20;i>=0;--i) {
if(dep[bz[y][i]]>=dep[x]) y=bz[y][i] ;
if(x==y) return y ;
}
for(int i=20;i>=0;--i) {
if(bz[x][i]!=bz[y][i]) {
x=bz[x][i] ;
y=bz[y][i] ;
}
}
return bz[x][0] ;
}
void qans(int x,int fa) {
ans[x]=1;
for(int i=0;i<tr[x].size();++i) {
int to=tr[x][i];
if(to==fa) continue;
qans(to,x);
ans[x]+=ans[to];
}
}
I int read() {
int ret=0; char ch;
while((ch=getchar())>'9'||ch<'0'); ret=ch-'0';
while((ch=getchar())>='0'&&ch<='9') ret=ret*10+ch-'0';
return ret;
}
signed main()
{
n=read(); m=read();
for(int i=1;i<=m;++i) {
int x,y; x=read(); y=read();
mkq[x].push_back(y);
mkrq[y].push_back(x);
}
for(int i=1;i<=n;++i) {
for(int j=mkq[i].size()-1;j>=0;--j) q[i].push_back(mkq[i][j]);
for(int j=mkrq[i].size()-1;j>=0;--j) rq[i].push_back(mkrq[i][j]);
}
for(int i=1;i<=n;++i) {
fa[i]=i;
semi[i]=i;
mina[i]=i;
}
dfs(1,0);
for(int i=n;i>=2;--i) {
int x=id[i],sx=n;
if(!x) continue;
for(int j=0;j<rq[x].size();++j) {
int fr=rq[x][j];
if(!dfn[fr]) continue;
if(dfn[fr]<dfn[x]) sx=min(sx,dfn[fr]);
else find(fr),sx=min(sx,dfn[semi[mina[fr]]]);
}
semi[x]=id[sx]; mina[x]=id[sx]; fa[x]=f[x];
}
builddag();
topusort();
for(int i=2;i<=n+1;++i) {
int rpos=tpid[i],lca=0;
if(rg[rpos].size()) lca=rg[rpos][0];
for(int j=1;j<rg[rpos].size();++j) lca=qlca(lca,rg[rpos][j]);
tr[lca].push_back(rpos); bz[rpos][0]=lca; dep[rpos]=dep[lca]+1;
for(int j=0;j<=19;++j) bz[rpos][j+1]=bz[bz[rpos][j]][j];
}
qans(0,0);
for(int i=1;i<=n;++i) cout<<ans[i]<<' ';
cout<<endl;
return 0;
}