1 条题解

  • 0
    @ 2025-8-24 23:17:34

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Rainbow_qwq
    **

    搬运于2025-08-24 23:17:34,当前版本为作者最后更新于2025-06-05 10:57:25,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这题的图是 Halin Graph,树宽为 33,可以构造 Halin Graph 树分解(code1),然后用逛公园一题树分解的做法解决(code2),复杂度 O(nlogn+q)O(n\log n+q)

    下面讲一点更 oi 的做法。

    画图会发现这是一张平面图,由最外面的一个环(连起了所有叶子)和中间的一棵树组成。

    对于这题,可以对树三度化,进行边分治。

    对于树上被切开的两个连通块,两部分之间最多有三条边相连(环上两条边,一条树边)。

    对于 O(1)O(1) 个这几条边上的点,作为起点跑一遍最短路,然后把当前的询问答案都 chkmin 一下。

    跨越两边的询问不必再递归,在同一边的询问递归下去,每个询问最多被递归 log\log 次。

    复杂度 O(nlog2n+qlogn)O(n\log^2 n+q\log n)

    #include<bits/stdc++.h>
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define int long long
    using namespace std;
    
    #define fi first
    #define se second
    #define pb push_back
    #define mkp make_pair
    typedef pair<int,int>pii;
    typedef vector<int>vi;
    
    #define maxn 400005
    #define inf 0x3f3f3f3f3f3f3f3f
    
    int n,nn,m,res[maxn];
    int qu[maxn],qv[maxn];
    int fa[maxn];
    vector<pii>G[maxn];
    
    struct edge{
    	int to,nxt,w;
    }e[maxn<<1];
    int tot=1,head[maxn];
    void adde(int u,int v,int w){
    	e[++tot]=(edge){v,head[u],w};
    	head[u]=tot;
    }
    void add(int u,int v,int w){
    	adde(u,v,w);
    	adde(v,u,w);
    }
    
    void rebuild(int u,int pa){
    	int lst=u;
    	for(auto it:G[u]){
    		int v=it.fi,w=it.se; 
    		if(v==pa)continue;
    		rebuild(v,u);
    		add(lst,++nn,0),add(nn,v,w);
    		lst=nn;
    	}
    }
    
    vector<pii>go[maxn];
    
    #define iter(i,u,v,w) for(int i=head[u],v=e[i].to,w=e[i].w;i;i=e[i].nxt,v=e[i].to,w=e[i].w)
    
    int allsz,mn,id,sz[maxn];
    bool vis[maxn<<1];
    void gete(int u,int pa){
    	sz[u]=1;
    	iter(i,u,v,w){
    		if(v==pa || vis[i])continue;
    		gete(v,u); sz[u]+=sz[v];
    		if(mn>max(sz[v],allsz-sz[v])) mn=max(sz[v],allsz-sz[v]),id=i;
    	}
    }
    
    int col[maxn];
    int st[maxn],top;
    
    namespace D{
    
    struct edge{
    	int to,nxt,w;
    }e[maxn<<1];
    int tot,head[maxn];
    void adde(int u,int v,int w){
    	e[++tot]=(edge){v,head[u],w};
    	head[u]=tot;
    }
    bool vis[maxn];
    void dij(int u,int*dis){
    	For(i,1,top) vis[st[i]]=0,dis[st[i]]=inf;
    	dis[u]=0;
    	priority_queue<pii,vector<pii>,greater<pii>>q;
    	q.push(mkp(0,u));
    	while(q.size()){
    		int u=q.top().se;q.pop();
    		if(vis[u])continue; vis[u]=1;
    		iter(i,u,v,w){
    			if(dis[v]>dis[u]+w){
    				dis[v]=dis[u]+w;
    				q.push(mkp(dis[v],v));
    			}
    		}
    	}
    }
    
    }
    
    void color(int u,int pa,int c){
    	col[u]=c;
    	st[++top]=u;
    	iter(i,u,v,w)if(!vis[i]&&v!=pa)color(v,u,c);
    }
    
    
    pii tmp[999]; int len,tw[999];
    int dis[9][maxn];
    void clear(){
    	For(i,1,top){
    		int u=st[i];
    		col[u]=0; D::head[u]=0;
    	}top=0; D::tot=0; len=0;
    }
    
    void solve(int u,vi qs){
    	if(allsz==1||!qs.size())return;
    	mn=inf,gete(u,0);
    	int x=e[id].to,y=e[id^1].to;
    	vis[id]=vis[id^1]=1;
    	vi qx,qy;
    	color(x,0,1);
    	color(y,0,2);
    	For(i,1,top){
    		int u=st[i];
    		iter(i,u,v,w){
    			if(!col[v])continue;
    			D::adde(u,v,w);
    			if(col[u]==1&&col[v]==2) tmp[++len]=mkp(u,v),tw[len]=w,assert(len<=3);
    		}
    		for(auto it:go[u]){
    			int v=it.fi,w=it.se;
    			if(!col[v])continue;
    			D::adde(u,v,w);
    			if(col[u]==1&&col[v]==2) tmp[++len]=mkp(u,v),tw[len]=w,assert(len<=3);
    		}
    	}
    	assert(len<=3);
    	For(i,1,len){
    		D::dij(tmp[i].fi,dis[i*2-1]);
    		D::dij(tmp[i].se,dis[i*2]);
    	}
    	for(auto it:qs){
    		int u=qu[it],v=qv[it];
    		if(col[u]>col[v])swap(u,v);
    		if(col[u]!=col[v]){
    			For(i,1,len){
    				res[it]=min(res[it],dis[i*2-1][u]+dis[i*2][v]+tw[i]);
    			}
    		}else{
    			if(col[u]==1){
    				For(i,1,len) res[it]=min(res[it],dis[i*2-1][u]+dis[i*2-1][v]);
    				qx.pb(it);
    			}else{
    				For(i,1,len) res[it]=min(res[it],dis[i*2][u]+dis[i*2][v]);
    				qy.pb(it);
    			}
    		}
    	}
    	clear();
    	allsz=sz[x],solve(x,qx);
    	allsz=sz[y],solve(y,qy);
    }
    
    int leaf[maxn],lcnt;
    
    signed main()
    {
    	n=read();nn=n;
    	For(i,2,n){
    		fa[i]=read(); int w=read();
    		G[i].pb(mkp(fa[i],w));
    		G[fa[i]].pb(mkp(i,w));
    	}
    	For(i,1,n) if(G[i].size()==1) leaf[lcnt++]=i;
    	For(i,0,lcnt-1){
    		int u=leaf[i],v=leaf[(i+1)%lcnt];
    		int w=read();
    		go[u].pb(mkp(v,w)),go[v].pb(mkp(u,w));
    	}
    	rebuild(1,0);
    	allsz=nn;
    	vi orz;
    	m=read();
    	For(i,1,m){
    		qu[i]=read(),qv[i]=read();
    		orz.pb(i);
    		res[i]=inf;
    	}
    	solve(1,orz);
    	For(i,1,m){
    		printf("%lld\n",res[i]);
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    12446
    时间
    6000ms
    内存
    1024MiB
    难度
    7
    标签
    递交数
    0
    已通过
    0
    上传者