社区讨论

5pts玄关求调,树剖+ST表

P1967[NOIP 2013 提高组] 货车运输参与者 2已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@mhj40s1w
此快照首次捕获于
2025/11/03 20:22
4 个月前
此快照最后确认于
2025/11/03 20:22
4 个月前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
const int maxm=5e4+5;
int n,m;
int dep[maxn],top[maxn],wc[maxn],pa[maxn],sz[maxn],dfn[maxn],rdfn[maxn],tot;
int fa[maxn],wei[maxn];
int lg[maxn],st[maxn][25];
int getf(int x){return x==fa[x]?fa[x]:fa[x]=getf(fa[x]);}
void uni(int x,int y){fa[getf(x)]=getf(y);}
struct edge{int v,w;};
struct edge2{int u,v,w;}ed[maxm];
bool cmp(edge2 a,edge2 b){return a.w>b.w;}
vector<edge> e[maxn];
void dfs1(int u,int p){
	dfn[u]=++tot;
	rdfn[tot]=u;
	dep[u]=dep[p]+1;
	pa[u]=p;
	sz[u]=1;
	for(auto[v,w]:e[u]){
		if(v==p)continue;
		wei[v]=w;
		dfs1(v,u);
		sz[u]+=sz[v];
		if(sz[v]>sz[wc[u]])wc[u]=v;
	}
}
void dfs2(int u,int tp){
	top[u]=tp;
	if(wc[u])dfs2(wc[u],tp);
	for(auto[v,w]:e[u]){
		if(v==pa[u]||v==wc[u])continue;
		dfs2(v,v);
	}
}
void init(){
	lg[1]=0;
	for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
	for(int i=1;i<=n;i++){
		if(pa[rdfn[i]]==0)continue;
		st[i][0]=wei[rdfn[i]];
	}
	for(int j=1;j<=lg[n];j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		}
	}
}
int query(int l,int r){
	if(l>r)return 0x3f3f3f3f;
	int k=lg[r-l+1];
	return min(st[l][k],st[r-(1<<k)+1][k]);
}
int getmin(int u,int v){
	int ans=0x3f3f3f3f;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		ans=min(ans,query(dfn[top[u]],dfn[u]));
		u=pa[top[u]];
	}
	if(u==v)return ans;
	if(dep[u]<dep[v])swap(u,v);
	ans=min(ans,query(dfn[v]+1,dfn[u]));
	return ans;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++)cin>>ed[i].u>>ed[i].v>>ed[i].w;
	sort(ed+1,ed+m+1,cmp);
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		int fu=getf(ed[i].u),fv=getf(ed[i].v);
		if(fu!=fv){
			uni(ed[i].u,ed[i].v);
			e[ed[i].u].push_back({ed[i].v,ed[i].w});
			e[ed[i].v].push_back({ed[i].u,ed[i].w});
		}
	}
	for(int i=1;i<=n;i++)if(!dfn[i])wei[i]=0x3f3f3f3f,dfs1(i,0),dfs2(i,i);
	init();
	int q;
	cin>>q;
	for(int i=1,u,v;i<=q;i++){
		cin>>u>>v;
		if(getf(u)!=getf(v))cout<<-1<<endl;
		else cout<<getmin(u,v)<<endl;
	}
	return 0;
}
(在你眼前的是一个LCA只会树剖不会倍增但是会ST表的稀有动物)

回复

5 条回复,欢迎继续交流。

正在加载回复...