Security Cameras

題目鏈接:Security Cameras


裸的支配樹,不知道爲什麼沒人寫。

首先我們對於B點,直接往上跳父親即可找到所有支配他的點。

但是我們要知道,跳父親的同時,父親是最近支配點,父親的父親的第二近的支配點。

所以最後reverse即可。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10,M=2e6;
int n,m,s,A,B;
struct Dominate_tree{
	int cnt,tot,res,f[N],fa[N];
	int head[N<<1],pre[N<<1],to[M<<1],nex[M<<1],lat[M],cdy[N<<1];
	int bel[M],val[M],sdom[M],idom[M];
	int dfn[M],id[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;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 dfs(int x,int fa){
		f[x]=fa;
		for(int i=cdy[x];i;i=nex[i])	dfs(to[i],x);
	}
	void init(){
		cnt=tot=0;
		for(int i=1;i<=n;i++){
			cdy[i]=head[i]=lat[i]=pre[i]=0;
			idom[i]=sdom[i]=dfn[i]=id[i]=f[i]=fa[i]=0;
		}
	}
	void solve(){
		cin>>n>>m;	init();
		cin>>A>>B;	s=A;
		for(int i=1,a,b;i<=m;i++)	
			scanf("%d %d",&a,&b),add(head,a,b),add(pre,b,a);
		work();	dfs(s,s);
		vector<int> res;
		while(B!=A)	res.push_back(B),B=f[B];
		res.push_back(A);
		reverse(res.begin(),res.end());
		printf("%d\n",res.size());
		for(int i:res)	printf("%d ",i);puts("");
	}
}t;
signed main(){
	int T;	cin>>T;	while(T--)	t.solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章