萌新求助QAQ
查看原帖
萌新求助QAQ
341034
abcde777楼主2021/8/8 19:49

支配树,用的是求出半支配点后转为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;
}


2021/8/8 19:49
加载中...