静态查询树上路径的最小边权

 

边权转点权: 将根节点设置 val[ rt ]=inf ,  每个边权转移到向下的点的点权

然后树剖查询要改一下

 

树剖后用线段树查询点权最小值

 

 

#include <bits/stdc++.h>
using namespace std ;
 const int N=5e5+4,M=N*2;
 #define int long long
 
 int n,nxt[M],hd[N],all,go[M],w[M];
 int dep[N],sz[N],fa[N],son[N];
 int dfn[N],id[N],pool,top[N];
 
 void add_(int x,int y,int z){
 	go[++all]=y,w[all]=z,
 	nxt[all]=hd[x],hd[x]=all;
 }
  struct Edge{
  	int x,y,z;
  }E[N];
  int cmp(Edge &x,Edge &y){
  	return x.z>y.z;
  }
  
  int F[N];
  int find(int x){
  	return x==F[x]?x:F[x]=find(F[x]);
  }
  void solve(int K){
  	sort(E+1,E+1+K,cmp);
  	for(int i=1;i<=K;i++){
  		int x=E[i].x,y=E[i].y,z=E[i].z;
  		int fx=find(E[i].x),fy=find(E[i].y);
  		if(fx!=fy){
  			add_(x,y,z); add_(y,x,z); 
  			F[fy]=fx;
  		}
  	}
  }
#define k1 k<<1
#define k2 k<<1|1
int vis[N],val[N] ;
  int a[N];
  struct Tree{
    int v;
  	int l,r;
  }tr[N<<2];
 
 #define inf 1e18
 int qry(int k,int x,int y){
     int t=inf;
     if(x<=tr[k].l&&y>=tr[k].r)
         return tr[k].v;
     
     int md=(tr[k].l+tr[k].r)/2; 
    
     if(x<=md) t=min(t,qry(k1,x,y));
     if(y>md) t=min(t,qry(k2,x,y));
     return t;
 }
 
 void build(int k,int l,int r){
 	tr[k].l=l,tr[k].r=r;
 	tr[k].v=inf;
 	
     if(l==r){
         tr[k].v=val[id[l]];  return;
     }
     int md=(l+r)/2;
     build(k1,l,md),build(k2,md+1,r);
     
      tr[k].v=min(tr[k1].v,tr[k2].v);
 }

 
 
 void dfs1(int x,int par){
 	vis[x]=1;
 	n++;
 	fa[x]=par;
 	sz[x]=1;
 	dep[x]=dep[par]+1;
 	son[x]=0;
 	
 	for(int i=hd[x];i;i=nxt[i]){
 		int y=go[i]; if(par==y) continue;
 			
 		val[y]=w[i];
		  dfs1(y,x);
 		sz[x]+=sz[y];
 		if(sz[y]>sz[son[x]]) son[x]=y;
	 }
 }
 void dfs2(int x,int topf){
 	dfn[x]=++pool;
 	id[pool]=x;
 	top[x]=topf;
 	if(!son[x]) return ;
 	dfs2(son[x],topf);
 	
 	for(int i=hd[x];i;i=nxt[i]){
 		int y=go[i]; 
 		if(y==fa[x]||y==son[x]) continue;
		  dfs2(y,y);
	 }
 }
 int qRange(int x,int y){
 	if(find(x)!=find(y)) return inf;
 	int res=inf;
 	while(top[x]!=top[y]){
 		if(dep[top[x]]<dep[top[y]]) swap(x,y);
 		res=min(res, qry(1,dfn[top[x]],dfn[x]));
 		
 		x=fa[top[x]];
	 }
	if(x==y) return res;
	 
	if(dep[x]>dep[y]) swap(x,y);
	res=min(res, qry(1,dfn[x]+1,dfn[y])) ;  //
	return res;
 }
 
 signed main(){
 	int num,K;
 	int i,x,y,tes;
 
 	cin>>num>>K;
 	for(i=1;i<=num;i++) F[i]=i;
 	for(i=1;i<=K;i++) 
 		cin>>E[i].x>>E[i].y>>E[i].z;
 	solve(K);
 
 	for(i=1;i<=num;i++){
 		if(vis[i]) continue;
 		
 		val[i]=inf;
	 	dfs1(i,0); dfs2(i,i);
 	}
 	build(1,1,n);
 	
 	cin>>tes;
 	while(tes--){
 		cin>>x>>y;
 		int ans=qRange(x,y);if(ans==inf) ans=-1;
 		cout<<ans<<endl;
	 }
 } 

 

posted on 2023-03-10 20:57  towboat  阅读(20)  评论(0)    收藏  举报