不理解我的虚树为何会跑得这么慢?
  • 板块学术版
  • 楼主Llx2022
  • 当前回复2
  • 已保存回复2
  • 发布时间2023/6/30 21:35
  • 上次更新2023/11/3 12:01:54
查看原帖
不理解我的虚树为何会跑得这么慢?
828664
Llx2022楼主2023/6/30 21:35

记录

#include<iostream>
#include<cstring>
#include<algorithm>
#include<bitset>
using namespace std;
const int N=2.5e5+9;
const int M=N*2;
int n,m,k,u,v;
long long ww;
int h[N],e[M],ne[M];
long long w[M];
int idx;
void add(int a,int b,long long c){
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
int h2[N],e2[M],ne2[M],idx2;
void add2(int a,int b){
	e2[idx2]=b;
	ne2[idx2]=h2[a];
	h2[a]=idx2++;
}
long long val[N];
int dfn[N],top[N],son[N],sz[N],father[N],dep[N],tm;
void dfs1(int u,int fa){
	sz[u]=1;
	father[u]=fa;
	dep[u]=dep[fa]+1;
	for(int i=h[u];~i;i=ne[i]){
		int v=e[i];
		if(v==fa) continue;
		val[v]=min(val[u],w[i]);
		dfs1(v,u);
		sz[u]+=sz[v];
		if(sz[v]>sz[son[u]]){
			son[u]=v;
		}
	}
}
void dfs2(int u,int fa){
	top[u]=fa;
	dfn[u]=++tm;
	if(son[u]) dfs2(son[u],fa);
	for(int i=h[u];~i;i=ne[i]){
		int v=e[i];
		if(v==father[u]||v==son[u]) continue;
		dfs2(v,v);
	}
}
int LCA(int a,int b){
	while(top[a]!=top[b]){
		if(dep[top[a]]<dep[top[b]]) swap(a,b);
		a=father[a];
	}
	if(dep[a]>dep[b]) swap(a,b);
	return a;
}
bool cmp(int a,int b){
	return dfn[a]<dfn[b];
}
int que[N];
bitset<N> ask;
int stk[N],topp;
long long dfs(int pos){
	long long sum=0;
	long long tem;
	for(int i=h2[pos];~i;i=ne2[i]){
		int v=e2[i];
		sum+=dfs(v);
	}
	if(ask[pos]){
		tem=val[pos];
	}
	else{
		tem=min(val[pos],sum);
	}
	ask[pos]=false;
	h2[pos]=-1;
	return tem;
}
signed main(){
	memset(h,-1,sizeof h);
	val[1]=1e18;
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		scanf("%d%d%lld",&u,&v,&ww);
		add(u,v,ww);
		add(v,u,ww);
	}
	dfs1(1,0);
	dfs2(1,1);
	memset(h2,-1,sizeof h2);
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		cin>>k;
		for(int j=1;j<=k;j++){
			scanf("%d",&que[j]);
			ask[que[j]]=1;
		}
		sort(que+1,que+1+k,cmp);
        stk[topp=1]=que[1];
		idx2=0;
        for(int j=2;j<=k;j++){
        	int now=que[j];
        	int lca=LCA(now,stk[topp]);
        	while(true){
        		if(dep[lca]>=dep[stk[topp-1]]){
        			if(lca!=stk[topp]){
        				add2(lca,stk[topp]);
        				if(lca!=stk[topp-1]){
        					stk[topp]=lca;
        				}
        				else{
        					topp--;
        				}
        			}
					break;
        		}
        		else{
        			add2(stk[topp-1],stk[topp]);
        			topp--;
        		}
        	}
        	stk[++topp]=now;
        }
		while(--topp){
			add2(stk[topp],stk[topp+1]);
		}
		printf("%lld\n",dfs(stk[1]));
	}
	return 0;
}
2023/6/30 21:35
加载中...