虚树 80pts,WA最后两个点
查看原帖
虚树 80pts,WA最后两个点
157884
Glassy_Sky楼主2023/10/19 09:33

RT

题意是求虚树上关键点的 最小路径,最大路径,路径总和

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e6+5,maxq=5e4+5;

struct Graph {
	int head[maxn],idx=0;
	struct edge {
		int v,next;
	}e[maxn<<1];
	inline void Add(int u,int v) {
		e[++idx]={v,head[u]};
		head[u]=idx;
	}
}T,V;

int dep[maxn],fa[maxn][22],dfn[maxn],dfnt=0;

void dfs(int now,int father) {
	dfn[now]=++dfnt;
	dep[now]=dep[father]+1;
	fa[now][0]=father;
	for(int i=1;i<=20;i++)
		fa[now][i]=fa[fa[now][i-1]][i-1];
	for(int i=T.head[now];i;i=T.e[i].next) {
		int v=T.e[i].v;
		if(v==father) continue;
		dfs(v,now);
	}
}

int LCA(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=20;i>=0;i--)
		if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
	if(x==y) return x;
	for(int i=20;i>=0;i--)
		if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}

int n,q,k,a[maxn<<1],rt;
bool guan[maxn];

bool cmp(int a,int b) {
	return dfn[a]<dfn[b];
}

void build() {
	sort(a+1,a+1+k,cmp);
	int len=k;
	for(int i=1;i<k;i++)
		a[++len]=LCA(a[i],a[i+1]);
	sort(a+1,a+1+len,cmp);
	len=unique(a+1,a+1+len)-a-1;
	V.idx=0;
	rt=0;
	for(int i=1;i<len;i++) {
		int lca=LCA(a[i],a[i+1]);
		if(!rt||dep[lca]<dep[rt]) rt=lca;
		V.Add(lca,a[i+1]);
	}
}

int siz[maxn];
long long dept[maxn],mn=1e18,sum=0,maxx[maxn],minn[maxn],mx=0;

void dfs2(int now) {
	if(guan[now]) {
		siz[now]=1;
		dept[now]=dep[now];
		maxx[now]=dep[now];
		minn[now]=dep[now];
	}
	else {
		siz[now]=0;
		dept[now]=0;
		maxx[now]=-1e15;
		minn[now]=1e15;
	}
	for(int i=V.head[now];i;i=V.e[i].next) {
		int v=V.e[i].v;
		dfs2(v);
		sum+=dept[now]*siz[v]+dept[v]*siz[now]-2*(siz[v]*siz[now])*dep[now];
		siz[now]+=siz[v];
		dept[now]+=dept[v];
		mn=min(mn,minn[v]+minn[now]-2*dep[now]);
		mx=max(mx,maxx[v]+maxx[now]-2*dep[now]);
		maxx[now]=max(maxx[now],maxx[v]);
		minn[now]=min(minn[now],minn[v]);
	}
	guan[now]=false;
	V.head[now]=0;
}

int main() {
	scanf("%d",&n);
	for(int i=1;i<n;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		T.Add(u,v);
		T.Add(v,u);
	}
	dfs(1,0);
	scanf("%d",&q);
	while(q--) {
		scanf("%d",&k);
		for(int i=1;i<=k;i++)
			scanf("%d",&a[i]),guan[a[i]]=true;
		build();
		mn=1e18,mx=0,sum=0;
		dfs2(rt);
		printf("%lld %lld %lld\n",sum,(mn>=1e10?1ll*0:mn),mx);
	}
	return 0;
}
2023/10/19 09:33
加载中...