Stable Members

題目鏈接:Stable Members


這道題似乎可以拓撲排序+染色做。我不會,於是直接支配樹了。

我們讓支配樹的唯一源點爲0點,然後建立反圖,根據支配樹的定義可知,每個點的支配點爲祖先。

所以這些點不被支配,則只有一個祖先就是0點,所以其實就是找0點的兒子。

由於要求最近支配點,不能0點,所以我們讓0點爲n+1即可。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10,M=N*20;
int n,s;
struct Dominate_tree{
	int cnt,tot,res;
	int head[N<<1],pre[N<<1],to[M<<1],nex[M<<1],lat[M],cdy[M];
	int bel[M],val[M],sdom[M],idom[M];
	int dfn[M],id[M],fa[M];
	inline void add(int *head,int a,int b){
		to[++tot]=b; nex[tot]=head[a]; head[a]=tot;
	}
	void dfs(int x){
		dfn[x]=++cnt;	id[cnt]=x;
		for(int i=head[x];i;i=nex[i]){
			if(dfn[to[i]])	continue;
			dfs(to[i]);	fa[to[i]]=x;
		}
	}
	int find(int x){
		if(x==bel[x])	return x;
		int rt=find(bel[x]);
		if(dfn[sdom[val[bel[x]]]]<dfn[sdom[val[x]]])	val[x]=val[bel[x]];
		return bel[x]=rt;
	}
	void Tarjan(){
		for(int i=cnt;i>=2;i--){
			int x=id[i];
			for(int j=pre[x];j;j=nex[j]){
				if(!dfn[to[j]])	continue;
				find(to[j]);
				if(dfn[sdom[val[to[j]]]]<dfn[sdom[x]])	sdom[x]=sdom[val[to[j]]];
			}
			add(lat,sdom[x],x);	bel[x]=fa[x]; x=fa[x];
			for(int j=lat[x];j;j=nex[j]){
				find(to[j]);
				if(sdom[val[to[j]]]==x)	idom[to[j]]=x;
				else	idom[to[j]]=val[to[j]];
			}
			lat[x]=0;
		}
		for(int i=2,x;i<=cnt;i++){
			x=id[i];
			if(idom[x]!=sdom[x])	idom[x]=idom[idom[x]];
		}
	}
	void work(){
		for(int i=1;i<=n+2;i++)	sdom[i]=bel[i]=val[i]=i;
		dfs(s);	Tarjan();	tot=0;
		for(int i=1;i<=n;i++)	if(idom[i])	add(cdy,idom[i],i);
	}
	void input(){
		cin>>n;	s=n+1;
		for(int i=1,k,x;i<=n;i++){
			scanf("%d",&k);
			while(k--){
				scanf("%d",&x);
				if(!x)	x=s;
				add(head,x,i),add(pre,i,x);
			}
		}
		work();
		for(int i=cdy[s];i;i=nex[i])	res++;
		cout<<res;
	}
}t;
signed main(){
	t.input();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章