两题差不多就一起写了

P4320-道路相遇

题目链接:https://www.luogu.com.cn/problem/P4320

题目大意

\(n\)个点\(m\)条边的一张图,\(q\)次询问两个点之间路径的必经点数量。

解题思路

建出圆方树然后问题就变为询问两个点之间路径的圆点数量,可以直接倍增\(LCA\)求。当然还有更方便的,因为这两个点是圆点,它们的路径一定是一圆一方,所以答案就是它们直接的路径长度\(len/2+1\)。也是倍增或者树剖\(LCA\)就好了。

时间复杂度\(O(n\log n)\)

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
const int N=1e6+10,T=20;
int n,m,t,dfc,dfn[N],low[N];
int dep[N],f[N][T+1];
vector<int> G[N],H[N];
stack<int> s;
void tarjan(int x){
dfn[x]=low[x]=++dfc;
s.push(x);
for(int y:G[x])
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]==dfn[x]){
int k;++n;
do{
k=s.top();s.pop();
H[n].push_back(k);
H[k].push_back(n);
}while(k!=y);
H[n].push_back(x);
H[x].push_back(n);
}
}
else low[x]=min(low[x],dfn[y]);
return;
}
void dfs(int x,int fa){
dep[x]=dep[fa]+1;
for(int y:H[x]){
if(y==fa)continue;
dfs(y,x);f[y][0]=x;
}
return;
}
int LCA(int x,int y){
if(dep[x]>dep[y])swap(x,y);
for(int i=T;i>=0;i--)
if(dep[f[y][i]]>=dep[x])
y=f[y][i];
if(x==y)return x;
for(int i=T;i>=0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
tarjan(1);dfs(1,0);
for(int j=1;j<=T;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
scanf("%d",&t);
while(t--){
int x,y,p;
scanf("%d%d",&x,&y);
p=LCA(x,y);
printf("%d\n",(dep[x]+dep[y]-2*dep[p])/2+1);
}
return 0;
}

P5058-[ZJOI2004]嗅探器

题目链接:https://www.luogu.com.cn/problem/P5058

题目大意

一张\(n\)个点\(m\)条边的无向图,给出两个点求它们之间编号最小的必经点。

解题思路

一组询问所以直接建好圆方树\(dfs\)就好了,如果多组询问的话也可以做,倍增维护树链最小值就好了。

这题是一组询问所以随便写\(O(n)\)

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
const int N=4e5+10;
int n,m,dfc,cnt,s,t,dfn[N],low[N];
vector<int> G[N],H[N];
stack<int> S;
void tarjan(int x){
dfn[x]=low[x]=++dfc;
S.push(x);
for(int y:G[x])
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]==dfn[x]){
int k;++cnt;
do{
k=S.top();S.pop();
H[cnt].push_back(k);
H[k].push_back(cnt);
}while(k!=y);
H[cnt].push_back(x);
H[x].push_back(cnt);
}
}
else low[x]=min(low[x],dfn[y]);
return;
}
int dfs(int x,int fa){
int k;
if(x==t)return n+1;
for(int y:H[x]){
if(y==fa)continue;
if(k=dfs(y,x))
return min((x==s)?(n+1):x,k);
}
return 0;
}
int main()
{
scanf("%d",&n);cnt=n;
while(1){
int x,y;
scanf("%d%d",&x,&y);
if(!x&&!y)break;
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
scanf("%d%d",&s,&t);
s=dfs(s,0);
if(s>n||!s)printf("No solution\n");
else printf("%d\n",s);
return 0;
}

P4320-道路相遇,P5058-[ZJOI2004]嗅探器【圆方树,LCA】的更多相关文章

  1. 【luogu4320】道路相遇 (圆方树 + LCA)

    Description ​ 给你一张\(~n~\)个点\(~m~\)条边的无向图,保证无重边无自环, 共\(~q~\)组询问求\(~x~\)到\(~y~\)的路径上必经的点数. Solution ​ ...

  2. Traffic Real Time Query System 圆方树+LCA

    题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...

  3. 【洛谷 P4320】 道路相遇 (圆方树,LCA)

    题目链接 题意:给一张无向图和\(M\)个询问,问\(u,v\)之间的路径的必经之点的个数. 对图建出圆方树,然后必经之点就是两点路径经过的原点个数,用\((dep[u]+dep[v]-dep[LCA ...

  4. luoguP4320 道路相遇 圆方树

    标题已经告诉你怎么做了..... 两点间的圆点个数即为所求 建出圆方树后打个树剖求$lca$就行..... 复杂度$O(n + q \log n)$ #include <cstdio> # ...

  5. 【刷题】洛谷 P4320 道路相遇

    题目描述 在 H 国的小 w 决定到从城市 \(u\) 到城市 \(v\) 旅行,但是此时小 c 由于各种原因不在城市 \(u\),但是小 c 决定到在中途与小 w 相遇 由于 H 国道路的原因,小 ...

  6. 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)

    orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...

  7. 仙人掌&圆方树

    仙人掌&圆方树 Tags:图论 [x] [luogu4320]道路相遇 https://www.luogu.org/problemnew/show/P4320 [ ] [SDOI2018]战略 ...

  8. Note -「圆方树」学习笔记

    目录 圆方树的定义 圆方树的构造 实现 细节 圆方树的运用 「BZOJ 3331」压力 「洛谷 P4320」道路相遇 「APIO 2018」「洛谷 P4630」铁人两项 「CF 487E」Touris ...

  9. [SDOI2018]战略游戏 圆方树,树链剖分

    [SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...

随机推荐

  1. 经典树与图论(最小生成树、哈夫曼树、最短路径问题---Dijkstra算法)

    参考网址: https://www.jianshu.com/p/cb5af6b5096d 算法导论--最小生成树 最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树. im ...

  2. wpf 自定义 RadioButton.

    <Style TargetType="RadioButton" x:Key="nav"> <Setter Property="Tem ...

  3. COM笔记-动态链接

    在实现了IUnknown之后,组件和客户之间只是一种非常松散的连接,这使用组件和客户各自可以发生变化而不会对对方造成什么影响. 下面讨论如何将组件放入到动态链接库(dll)中. 关于DLL更多内容可以 ...

  4. canvas——离屏

    离屏操作: 1.创建一个新的离屏canvas; 2.把一些复杂额绘画操作(背景),画在离屏canvas上: 3.将离屏canvas通过drawImage(离屏canvas对象,x1,y1,offcan ...

  5. 测试linux python import module

    源码test.py #!/usr/bin/env python # -*- coding: UTF-8 -*- import os os.system("df -h") 运行结果( ...

  6. 用C++实现的增强Euler筛法程序

    运行示例 PS H:\Read\num\x64\Release> .\eulerSievePro EulerSievePro: a method to find out all primes b ...

  7. GO的GC辣鸡回收(一)

    用户程序通过内存分配器(Allocator)在堆上申请内存,而垃圾收集器(Collector)负责回收堆上的内存空间,内存分配器和垃圾收集器共同管理程序中的堆内存空间. 基本概念 垃圾分类 语义垃圾: ...

  8. Windows内核基础知识-8-监听进程、线程和模块

    Windows内核基础知识-8-监听进程.线程和模块 Windows内核有一种强大的机制,可以在重大事件发送时得到通知,比如这里的进程.线程和模块加载通知. 本次采用链表+自动快速互斥体来实现内核的主 ...

  9. C#多线程开发-线程池03

    你好,我是阿辉. 前面2篇文章介绍了线程的基础知识和线程同步,下面我们来一起认识学习下,线程池的使用. 线程池 创建线程是昂贵的操作,所以为每个短暂的异步操作创建线程会产生显著的开销.一般情况下,都会 ...

  10. python 常用的文件操作命令

    一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法. 1.得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 2.返回指定目录下的所有文件 ...