首页 > 其他分享 >【XSY2418】修路(最短路图,支配)

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

时间:2022-10-30 10:24:57浏览次数:35  
标签:ch 修路 int 短路 vis fa XSY2418 now dis

首先可以 \(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;
}

标签:ch,修路,int,短路,vis,fa,XSY2418,now,dis
From: https://www.cnblogs.com/ez-lcw/p/16840594.html

相关文章

  • 【SCOI2007】k短路(A_)
    考虑用\(A^*\)维护这个东西,由于其它题解都讲得很清楚\(A^*\)的原理了,我就在这里说一下这题需要注意的地方。按照\(A^*\)的套路,我们要把估价函数设为当前点到\(b\)......
  • 【CF1253F】Cheap Robot(最小生成树,最短路)
    首先发现所有询问点都是充电桩这个条件很有用。它能滋生出一种暴力到极端的想法:用Floyd对全局跑一遍最短路。然后新建一个图,图中两两充电桩连一条边,边权为它们之间的最......
  • python | 算法-最短路径-dijikstra改进算法
    写在前面:我自己用python练习算法与数据结构的典型算法汇总在这里:汇总-算法与数据结构-python版,欢迎翻阅!1️⃣参考链接:https://github.com/algorithmzuo/algorithmbasic......
  • BFS最短路径(求x到y的最少计算次数)
     给定两个-100到100的整数x和y,对x只能进行加1,减1,乘2操作,问最少对x进行几次操作能得到y?例如:a=3,b=11:可以通过3*2*2-1,3次操作得到11;a=5,b=8:可以通过(5-1)*2,2次操作得到......
  • BFS--宽搜求最短路径
    1010#S######.#......#..#.#.##.##.#.#........##.##.####....#....#.#######.#....#......####.###.....#...G##是障碍,.是通道,S是起点,G是终点求出最短路径长度......
  • 并查集--同时修路得到的最短时间
    题目背景AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。题目描述给出A地区的村庄数NN,和公路数MM,公路是双向的。并告诉你每条公路的连......
  • BZOJ 1001([BeiJing2006]狼抓兔子-最大流转对偶图最短路)
    1001:[BeiJing2006]狼抓兔子TimeLimit: 15Sec  MemoryLimit: 162MBSubmit: 5779  Solved: 1297​​Submit​​][​​Status​​][​​Discuss​​]D......
  • 最短路问题
                   ......
  • 深度优先搜索求最短路径DFS C#实现
    搜索效果 C#项目文件可以点击下载   搜索最短路径的代码:///<summary>///DFS求最短路径///</summary>///<paramname="cX">当前点X坐标</param>///<par......
  • 次短路与 k 短路
    次短路严格次短路基本思路:两个dis数组分别储存最短路和次短路,依然使用堆优Dij。显然,堆优部分是不变的。structnode{ intid,val; booloperator<(constnode&b......