题目内容

洛谷链接

给出一个\(n\)个节点,\(m\)条边的无向图和两个节点\(s\)和\(t\),问这两个节点的路径中有几个点必须经过。

输入格式

第一行是\(n\)和\(m\)。

接下来\(m\)行,给出两个数表示这两个节点之间存在一条边。

接下来一行一个整数\(Q\),表示询问个数。

接下来\(Q\)行,每行两个整数\(s\)和\(t\)(\(s\not= t\))。

数据范围

\(0<n\le 10000,0<m\le 100000,0<Q\le 10000,0<s,t\le m\)

输出格式

对于每个询问,输出一行表示答案

样例输入

5 6

1 2

1 3

2 3

3 4

4 5

3 5

2

2 3

2 4

0 0

样例输出

0

1

思路

这个题问的就是\(s\)到\(t\)路径上割点的个数。

点双缩点,可以知道,每条边仅在一个联通块中,把割点和它相邻的联通块建边,从而构造棵树。

询问\(s\)边和\(t\)边,需要求它们分别属于哪个连通块。所以问题转化成了一棵树中,有些点已标记为割点,询问两个非割点之间路径上有多少个割点。

因此选择一个点作为树根,求出每个点到树根路径上有多少个割点,然后对于询问的两个点求一次LCA即可。

代码

#include<cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=10000+10;
const int maxm=100000+10; struct Edge{
int u,to,next,vis,id;
}edge[maxm<<1]; int head[maxn<<1],dfn[maxn<<1],low[maxn],st[maxm],iscut[maxn],subnet[maxn],bian[maxm];
int cnt,time,top,btot;
vector<int> belong[maxn]; void add(int u,int to){
edge[cnt].u=u;
edge[cnt].to=to;
edge[cnt].next=head[u];
edge[cnt].vis=0;
head[u]=cnt++;
} void init(int n){
for(int i=0;i<=n;i++){
head[i]=-1;
dfn[i]=iscut[i]=subnet[i]=0;
belong[i].clear();
}
cnt=time=top=btot=0;
} void dfs(int u){
dfn[u]=low[u]=++time;
for(int i=head[u];i!=-1;i=edge[i].next){
if(edge[i].vis)continue;
edge[i].vis=edge[i^1].vis=1;
int to=edge[i].to;
st[++top]=i;
if(!dfn[to]){
dfs(to);
low[u]=min(low[u],low[to]);
if(dfn[u]<=low[to]){
subnet[u]++;
iscut[u]=1;
btot++;
do{
int now=st[top--];
belong[edge[now].u].push_back(btot);
belong[edge[now].to].push_back(btot);
bian[edge[now].id]=btot;
to=edge[now].u;
}while(to!=u);
}
}
else
low[u]=min(low[u],low[to]);
}
} int B[maxn<<2],F[maxn<<2],d[maxn<<2][20],pos[maxn<<2],tot,dep[maxn<<1];
bool treecut[maxn<<1];
void RMQ1(int n){
for(int i=1;i<=n;i++)d[i][0]=B[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+j-1<=n;i++)
d[i][j]=min(d[i][j-1],d[i + (1<<(j-1))][j-1]);
} int RMQ(int L,int R){
int k=0;
while((1<<(k+1))<=R-L+1) k++;
return min(d[L][k],d[R-(1<<k)+1][k] );
} int lca(int a,int b){
if(pos[a] > pos[b])swap(a,b);
int ans=RMQ(pos[a],pos[b]);
return F[ans];
} //写了个RMQ求LCA
void DFS(int u){
dfn[u]=++time;
B[++tot]=dfn[u];
F[time]=u;
pos[u]=tot;
for(int i=head[u];i!=-1;i=edge[i].next){
int to=edge[i].to;
if(!dfn[to]){
if(treecut[u])
dep[to]=dep[u] + 1;
else
dep[to]=dep[u];
DFS(to);
B[++tot]=dfn[u];
}
}
} void solve(int n){
for(int i=0;i<=n;i++) {
dfn[i]=0;
} time=tot=0;
for(int i=1;i<=n;i++)
if(!dfn[i]){
dep[i]=0;
DFS(i);
}
RMQ1(tot);
int m,u,to;
scanf("%d",&m);
while(m--){
scanf("%d%d",&u,&to);
u=bian[u];to=bian[to];
if(u<0||to<0){
printf("0\n");continue;
}
int LCA=lca(u,to);
if(u==LCA)
printf("%d\n",dep[to]-dep[u]-treecut[u]);
else if(to == LCA)
printf("%d\n",dep[u]-dep[to]-treecut[to]);
else
printf("%d\n",dep[u]+dep[to]-2*dep[LCA]-treecut[LCA]);
}
} int main(){
int n,m,u,to;
while(scanf("%d%d",&n,&m)!=-1 && n){
init(n);
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&to);
edge[cnt].id=i;
add(u,to);
edge[cnt].id=i;
add(to,u);
} for(int i=1;i<=n;i++)
if(!dfn[i]){
dfs(i);
subnet[i]--;
if(subnet[i]<=0)iscut[i]=0;
} int ditot=btot;
for(int i=1;i<=btot;i++)
treecut[i]=0;
for(int i=1;i<=btot+n;i++)
head[i]=-1;
cnt=0;
for(int i=1;i<=n;i++)
if(iscut[i]){
sort(belong[i].begin(),belong[i].end());
ditot++;
treecut[ditot]=1;
add(belong[i][0],ditot);
add(ditot,belong[i][0]);
for(int j=1;j<belong[i].size();j++)
if(belong[i][j]!=belong[i][j-1]){
add(belong[i][j],ditot);
add(ditot,belong[i][j]);
}
}
solve(ditot);
}
return 0;
}

【Targan+LCA】HDU 3686 Traffic Real Time Query的更多相关文章

  1. HDU 3686 Traffic Real Time Query System (图论)

    HDU 3686 Traffic Real Time Query System 题目大意 给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个. solution ...

  2. hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA。这题有重边!!!

    http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能 ...

  3. HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)

    Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...

  4. HDU 3686 Traffic Real Time Query System(点双连通)

    题意 ​ 给定一张 \(n\) 个点 \(m\) 条边的无向图,\(q\) 次询问,每次询问两边之间的必经之点个数. 思路 ​ 求两点之间必经之边的个数用的是边双缩点,再求树上距离.而对比边双和点双之 ...

  5. 【刷题】HDU 5869 Different GCD Subarray Query

    Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...

  6. 【线段树】HDU 5493 Queue (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5493 题目大意: N个人,每个人有一个唯一的高度h,还有一个排名r,表示它前面或后面比它高的人的个数 ...

  7. 【归并排序】【逆序数】HDU 5775 Bubble Sort

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 题目大意: 冒泡排序的规则如下,一开始给定1~n的一个排列,求每个数字在排序过程中出现的最远端 ...

  8. 【线段树】HDU 5443 The Water Problem

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5443 题目大意: T组数据.n个值,m个询问,求区间l到r里的最大值.(n,m<=1000) ...

  9. 【刷题】HDU 2222 Keywords Search

    Problem Description In the modern time, Search engine came into the life of everybody like Google, B ...

随机推荐

  1. Java的枚举简单应用

    /** * 请用枚举方式实现如下应用: * 客户去旅店住房, * 客户分普通客户,和vip客户,vip分白金和钻石客户 * 不同的客户有不同的折扣 * 入住的房间分单人房,双人房和套房 * 不同的房间 ...

  2. javascript事件环微任务和宏任务队列原理

    哈喽!大家好!我是木瓜太香,我又来嘞,今天来说说前端面试中经常别问到的 JS 事件环问题. JS 事件环 JS 程序的运行是离不开事件环机制的,这个机制保证在发生某些事情的时候我们有机会执行一个我们事 ...

  3. 转发请求RequestDispatcher()方法用于与页面的交互

    jsp1代码 <form action="HelloServlet" > 账号: <input type="text" name=" ...

  4. 【原创】K8S使用ceph-csi持久化存储之RBD

    一.集群和组件版本 K8S集群:1.17.3+Ceph集群:Nautilus(stables)Ceph-CSI:release-v3.1snapshotter-controller:release-2 ...

  5. Docker:三、深入Docker容器&Asp.net发版

    各位看官,我们前面已经有过两篇文章的研究了,哈哈,都是皮毛... 今天我们来看看docker容器内部,一探究竟... 一.进入docker容器 进入Linux容器非常简单,直接使用如下命令即可: do ...

  6. 龙芯3A4000-Debian 10上常用软件记录

    所用平台 硬件:龙芯3a4000 (MIPS64el) 操作系统:Debian 10(buster)+ MATE桌面 内核版本:4.19.90 以下所有软件同样适用于x86体系结构的Linux发行版. ...

  7. 关于excel表格中只复制筛选后的数据

    今天笔者在整个一个表格中的数据,需要将原表格的数据根据一些条件筛选后,整理到新的excel表中 但是发现每次操作,都将筛选条件之外的数据也粘贴进去了,但笔者确实又只选中了部分数据 经过多种方式尝试后, ...

  8. 论文阅读笔记: Natural Language Inference over Interaction Space

    这篇文章提出了DIIN(DENSELY INTERACTIVE INFERENCE NETWORK)模型. 是解决NLI(NATURAL LANGUAGE INFERENCE)问题的很好的一种方法. ...

  9. kafka面试总结

    本文为复习期间面试总结 从以下方面对kafka面试进行总结:基本原理架构/项目实践/生产者/消费者/协调者/存储层/控制器 基本原理架构 简单讲下什么是kafka[一句话概括/架构图] 消息队列选型 ...

  10. Python-全局函数(内置方法、内置函数)

    Python有很多内置方法,这些都全局可用 abs() 求数值的绝对值,如果是复数则返回其模 print(abs(-17), abs(30.2), abs(3+4j)) # Python中复数表示为 ...