性感代码,玄关求调
查看原帖
性感代码,玄关求调
637073
wujingfey楼主2023/10/11 22:05

虚树,RE on #11

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int n,q,k,ans;
int dep[N],sz[N],fa[N],top[N],son[N];//树剖数组 
vector<int> e[N];//原图
vector<int> ee[N];//虚树图
int s[N],tp;//手写栈
int dfn[N],tot,a[N],val[N],flag;//虚树数组 
void dfs1(int u,int f){
	fa[u]=f;
	sz[u]=1;
	dep[u]=dep[f]+1;
	dfn[u]=++tot;
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i];
		if(v==f) continue;
		dfs1(v,u);
		sz[u]+=sz[v];
		if(sz[u]>sz[son[u]]) son[u]=v;
	}
}
void dfs2(int u,int t){
	top[u]=t;
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i];
		if(v==fa[u]) continue;
		if(v==son[u]) dfs2(v,t);
		else dfs2(v,v);
	}
}
int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]>dep[top[y]]) x=fa[top[x]];
		else y=fa[top[y]];
	}
	return dep[x]<dep[y]?x:y;
}
bool cmp(int a1,int a2){
	return dfn[a1]<dfn[a2];//按照dfs序顺序排列 
}
void build(){//建立虚树 
	s[++tp]=1;//建立根
	if(a[1]!=1) s[++tp]=a[1];//特判1号询问点是不是根 
	for(int i=2;i<=k;i++){//依次加入询问点 
		int lca=LCA(s[tp],a[i]);
		while(tp>1 && dep[s[tp-1]]>=dep[lca]){//保证树根不被弹出,且弹出后的栈顶在lca以下 
			ee[s[tp-1]].push_back(s[tp]);//出栈连边
			tp--; 
		}//现在剩下一个栈顶元素,对应深度大于等于lca 
		/*---------------------------*/
		//讨论栈顶元素与lca的关系
		if(lca!=s[tp]){
			ee[lca].push_back(s[tp]);//lca向s[top]连边
			s[tp]=lca;//lca替换栈顶元素 
		}
		s[++tp]=a[i];//a[i]入栈 
	}
	while(tp){//处理最后一条链 
		ee[s[tp-1]].push_back(s[tp]); 
		tp--;
	}
}
void check(int u){
	if(val[u]&&val[fa[u]]) flag=1;
	for(int i=0;i<ee[u].size();i++){
		int v=ee[u][i];
		check(v);
	}
}
void rebuild(int u){
	val[u]=0;
	for(int i=0;i<ee[u].size();i++){
		int v=ee[u][i];
		rebuild(v);
	}
	ee[u].clear();
}
void DP(int u){
	if(val[u]){//是查询点 
		for(int i=0;i<ee[u].size();i++){
			int v=ee[u][i];
			DP(v);
			if(val[v]>=1){//子节点有查询点,说明要断掉u->v的路径上的点 
				ans++;
				val[v]=0;//把标记归零 
			}
		}
	}else{//不是查询点 
		for(int i=0;i<ee[i].size();i++){
			int v=ee[u][i];
			DP(v);
			val[u]+=val[v];
			val[v]=0;
		}
		if(val[u]>=2){//超过两个点相连,说明这个点要删除 
			ans++;
			val[u]=0;
		}
	}
	ee[u].clear();//摧毁虚树 
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n;
	for(int i=1;i<n;i++){
		int a,b;
		cin>>a>>b;
		e[a].push_back(b);
		e[b].push_back(a);
	}
	dfs1(1,0);
	dfs2(1,1);//预处理树剖求LCA 
	cin>>q;
	for(int cas=1;cas<=q;cas++){
		cin>>k;
		for(int i=1;i<=k;i++) cin>>a[i];
		/*-----------------------------------*/ 
		sort(a+1,a+1+k,cmp);//dfn序排序
		val[1]=0;
		build();//建虚树
		/*-----------------------------------*/
		ans=0;
		for(int i=1;i<=k;i++){
			val[a[i]]=1;//让所有查询点权值为1 
		}
		/*-----------------------------------*/
		flag=0;
		check(1);
		if(flag==1){
			cout<<-1<<endl;
			rebuild(1);
			continue;
		}
		/*-----------------------------------*/
		DP(1);
		cout<<ans<<"\n";
	}
	return 0;
}

(为了防止巨佬们嫌弃我丑陋的马蜂,我写上了注释,求调啊 T^T)

2023/10/11 22:05
加载中...