【XSY2418】修路(最短路图,支配)

首先可以 \(O(m\log n)\) 按题意把树建出来,显然这是一棵最短路图的生成树。

那么询问 \(u,v\) 相当于在树上 \((u,v)\) 路径上找到深度最深的一点 \(w\),满足最短路图中刨掉树上路径 \((u,w)\) 上的边后仍有从根到达 \(v\) 的路径。

考虑处理出 \(f(u)\) 表示 \(u\) 深度最浅的祖先满足 \(f(u)\) 能通过非树上路径 \((f(u),u)\) 上的边在最短路图中到达 \(u\)

在最短路图上使用拓扑排序从非树边转移即可得到 \(f(u)\)

那么每次询问 \(u,v\) 相当于在树上 \((u,v)\) 路径上找到深度最深的一个点 \(w\),满足 \(d_{f(w)}\leq d_u\)。使用倍增维护 \(d\) 的最小值即可。

时间复杂度 \(O((n+m+q)\log n)\)

#include<bits/stdc++.h>

#define LN 17
#define N 100010
#define M 200010
#define ll long long
#define INF 0x7fffffff

using namespace std;

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int node;
int n,m,s,ty;

namespace Tree
{
	int cnt,head[N],to[N],nxt[N];
	int d[N],fa[N][LN];
	int minn[N][LN];
	void adde(int u,int v)
	{
		to[++cnt]=v;
		nxt[cnt]=head[u];
		head[u]=cnt;
	}
	void dfs(int u)
	{
		for(int i=1;i<=16;i++)
			fa[u][i]=fa[fa[u][i-1]][i-1];
		for(int i=head[u];i;i=nxt[i])
		{
			int v=to[i];
			fa[v][0]=u,d[v]=d[u]+1;
			dfs(v);
		}
	}
	void init()
	{
		d[s]=1;
		dfs(s);
		for(int i=0;i<=16;i++) minn[0][i]=INF;
	}
	void initf(int u,int val)
	{
		minn[u][0]=val;
		for(int i=1;i<=16;i++)
			minn[u][i]=min(minn[u][i-1],minn[fa[u][i-1]][i-1]);
	}
	int getlca(int a,int b)
	{
		if(d[a]<d[b]) swap(a,b);
		for(int i=16;i>=0;i--)
			if(d[fa[a][i]]>=d[b])
				a=fa[a][i];
		if(a==b) return a;
		for(int i=16;i>=0;i--)
			if(fa[a][i]!=fa[b][i])
				a=fa[a][i],b=fa[b][i];
		return fa[a][0];
	}
	int getmin(int u,int f)
	{
		int ans=INF;
		for(int i=16;i>=0;i--)
			if(d[fa[u][i]]>=d[f])
				ans=min(ans,minn[u][i]),u=fa[u][i];
		return min(ans,minn[u][0]);
	}
	int query(int f,int u)
	{
		for(int i=16;i>=0;i--)
			if(d[fa[u][i]]>=d[f]&&minn[u][i]>d[f])
				u=fa[u][i];
		return d[u]-d[f];
	}
}

namespace DAG
{
	int cnt,head[N],to[M],nxt[M];
	int du[N];
	int f[N];
	void adde(int u,int v)
	{
		du[v]++;
		to[++cnt]=v;
		nxt[cnt]=head[u];
		head[u]=cnt;
	}
	queue<int>q;
	void main()
	{
		for(int i=1;i<=n;i++) f[i]=Tree::d[i];
		q.push(s);
		while(!q.empty())
		{
			int u=q.front();
			q.pop();
			Tree::initf(u,f[u]);
			for(int i=head[u];i;i=nxt[i])
			{
				int v=to[i];
				if(Tree::fa[v][0]!=u)
				{
					int lca=Tree::getlca(u,v);
					f[v]=min(f[v],Tree::getmin(u,lca));
				}
				du[v]--;
				if(!du[v]) q.push(v);
			}
		}
	}
}

namespace Graph
{
	int p[N];
	int cnt,head[N],nxt[M<<1],to[M<<1],w[M<<1];
	ll dis[N];
	void adde(int u,int v,int wi)
	{
		to[++cnt]=v;
		w[cnt]=wi;
		nxt[cnt]=head[u];
		head[u]=cnt;
	}
	namespace Dijkstra
	{
		struct data
		{
			int u;ll s;
			data(){};
			data(int a,ll b){u=a,s=b;}
			bool operator < (const data &a) const
			{
				return s>a.s;
			}
		};
		priority_queue<data>q;
		bool vis[N];
		void main()
		{
			memset(dis,127,sizeof(dis));
			dis[s]=0;
			q.push(data(s,0));
			while(!q.empty())
			{
				data now=q.top();
				q.pop();
				if(vis[now.u]) continue;
				vis[now.u]=1;
				for(int i=head[now.u];i;i=nxt[i])
				{
					int v=to[i];
					if(dis[now.u]+w[i]<dis[v])
					{
						dis[v]=dis[now.u]+w[i];
						q.push(data(v,dis[v]));
					}
				}
			}
		}
	}
	struct data
	{
		int v,p;
		data(){};
		data(int a,int b){v=a,p=b;}
		bool operator < (const data &a) const
		{
			return p>a.p;
		}
	};
	bool vis[N];
	priority_queue<data>q[N];
	void dfs(int u)
	{
		vis[u]=1;
		for(int i=head[u];i;i=nxt[i])
		{
			int v=to[i];
			if(dis[u]+w[i]==dis[v])
				q[u].push(data(v,p[v]));
		}
		while(!q[u].empty())
		{
			data now=q[u].top();
			q[u].pop();
			DAG::adde(u,now.v);
			if(vis[now.v]) continue;
			Tree::adde(u,now.v);
			dfs(now.v);
		}
	}
	void main()
	{
		for(int i=1;i<=n;i++) p[i]=read();
		for(int i=1;i<=m;i++)
		{
			int u=read(),v=read(),w=read();
			adde(u,v,w),adde(v,u,w);
		}
		Dijkstra::main();
		dfs(s);
	}
}

int main()
{
	n=read(),m=read(),s=read(),ty=read();
	Graph::main();
	Tree::init();
	DAG::main();
	int q=read(),lans=0;
	while(q--)
	{
		int u=read(),v=read();
		if(ty) u^=lans,v^=lans;
		printf("%d\n",lans=Tree::query(u,v));
	}
	return 0;
}
posted @ 2022-10-30 10:08  ez_lcw  阅读(12)  评论(0编辑  收藏  举报