题目大意:

  有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个。

思路:

  先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求LCA计算。

  注意:数组范围。

代码:

 #include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=,M=;
int u[M<<],v[M<<],nex[M<<],id[M<<],hea[N<<],dfn[N<<],low[N],st[M],sub[N],edge[M],
fa[N<<][],f[N<<],pos[N<<],dep[N<<];
bool vis[M<<],iscut[N],treecut[N<<];
int tim,top,tot,cnt,num;
vector <int> belo[N]; int read()
{
int x=; char ch=getchar();
while (ch<'' || ch>'') ch=getchar();
while (ch>='' && ch<='') x=(x<<)+(x<<)+ch-,ch=getchar();
return x;
} void add(int x,int y) { v[cnt]=y,u[cnt]=x,nex[cnt]=hea[x],vis[cnt]=,hea[x]=cnt++; } void tarjan(int x)
{
dfn[x]=low[x]=++tim;
for (int i=hea[x];~i;i=nex[i])
if (!vis[i])
{
int y=v[i]; st[++top]=i;
vis[i]=vis[i^]=;
if (!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
if (low[y]>=dfn[x])
{
++sub[x],++num;
iscut[x]=;
do
{
int now=st[top--];
belo[u[now]].push_back(num);
belo[v[now]].push_back(num);
edge[id[now]]=num;
y=u[now];
}while (y^x);
}
}
else low[x]=min(low[x],dfn[y]);
}
} void dfs(int x)
{
dfn[x]=++tim; fa[++tot][]=dfn[x];
f[tim]=x; pos[x]=tot;
for (int i=hea[x];~i;i=nex[i])
{
int y=v[i];
if (!dfn[y])
{
dep[y]=dep[x]+treecut[x];
dfs(y); fa[++tot][]=dfn[x];
}
}
} void RMQ(int n)
{
for (int j=;(<<j)<=n;++j)
for (int i=;i+j-<=n;++i)
fa[i][j]=min(fa[i][j-],fa[i+(<<j-)][j-]);
} int lca(int x,int y)
{
if (pos[x]<pos[y]) swap(x,y);
int k=;
while (<<(k+)<=pos[x]-pos[y]+) ++k;
return f[min(fa[pos[y]][k],fa[pos[x]-(<<k)+][k])];
} void wk(int n)
{
int i,m,x,y;
for (tim=tot=i=;i<=n;++i) dfn[i]=;
for (i=;i<=n;++i)
if (!dfn[i]) dep[i]=,dfs(i);
RMQ(tot);
for (m=read();m--;)
{
x=edge[read()],y=edge[read()];
if (x< || y<) { puts(""); continue; }
int z=lca(x,y);
if (x==z) printf("%d\n",dep[y]-dep[x]-treecut[x]);
else if (y==z) printf("%d\n",dep[x]-dep[y]-treecut[y]);
else printf("%d\n",dep[x]+dep[y]-(dep[z]<<)-treecut[z]);
}
} int main()
{
int n,m;
while (~scanf("%d%d",&n,&m))
{
int i; cnt=top=num=tim=;
if (!(n+m)) break;
for (i=;i<=n;++i) hea[i]=-,dfn[i]=sub[i]=iscut[i]=,belo[i].clear();
for (i=;i<=m;++i)
{
int x=read(),y=read();
id[cnt]=i,add(x,y),id[cnt]=i,add(y,x);
}
for (i=;i<=n;++i)
if (!dfn[i])
{
tarjan(i);
if (--sub[i]<=) iscut[i]=;
}
for (i=;i<=num;++i) treecut[i]=;
for (i=;i<=num+n;++i) hea[i]=-;
cnt=;
for (i=;i<=n;++i)
if (iscut[i])
{
sort(belo[i].begin(),belo[i].end());
treecut[++num]=;
add(belo[i][],num),add(num,belo[i][]);
for (int j=;j<belo[i].size();++j)
if (belo[i][j]^belo[i][j-]) add(belo[i][j],num),add(num,belo[i][j]);
}
wk(num);
}
return ;
}

UVALive-4839 HDU-3686 Traffic Real Time Query System 题解的更多相关文章

  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)(2010 Asia Hangzhou Regional Contest)

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

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

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

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

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

  5. HDU3686 Traffic Real Time Query System 题解

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

  6. 【Targan+LCA】HDU 3686 Traffic Real Time Query

    题目内容 洛谷链接 给出一个\(n\)个节点,\(m\)条边的无向图和两个节点\(s\)和\(t\),问这两个节点的路径中有几个点必须经过. 输入格式 第一行是\(n\)和\(m\). 接下来\(m\ ...

  7. 【HDOJ】3686 Traffic Real Time Query System

    这题做了几个小时,基本思路肯定是求两点路径中的割点数目,思路是tarjan缩点,然后以割点和连通块作为新节点见图.转化为lca求解.结合点——双连通分量与LCA. /* 3686 */ #includ ...

  8. CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System

    逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...

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

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

随机推荐

  1. echarts饼图

    1.添加点击事件并跳转到不同的页面 // 路径配置 require.config({ paths: { echarts: 'http://echarts.baidu.com/build/dist/' ...

  2. 【CQOI2011】动态逆序对 BZOJ3295

    Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...

  3. varchar后面是否定义长度,还是有区别的

    ' ' PRINT @year 结果是:2 ) ,' ' PRINT @year 结果是:2015 varchar是否定义长度,还是有区别的,不定义长度的时候,并非我想象中按照实际赋值自动填充,似乎默 ...

  4. 实现放大转场动画 from cocoachina

    原文1:http://www.cocoachina.com/ios/20160318/15714.html 原文2:http://ningandjiao.iteye.com/blog/2049105 ...

  5. ThinkPHP学习总结

    ThinkPHP学习总结 网站开发使用的thinkPHP5.0在此总结备查 MVC关系功能图 一.Thinkphp开发规范 l 类 类库.函数文件统一以.php为后缀: 类的文件名均以命名空间定义,并 ...

  6. 通过挂载系统光盘搭建本地yum仓库的方法

    在CentOS系统中,我们常常会安装大量的软件,但许多软件包都存在需要依赖性,当然我们可以通过一一安装依赖包来完成安装,但对于有些软件包需要大量的依赖包,再一一安装起来会显得特别麻烦.接下来我们就来讲 ...

  7. 解决NetBeans运行web项目时出现的“未能正确设置java DB”问题

    1.在NetBeans导航器中,点击"服务"选项卡: 2.展开"数据库"菜单: 3.在"Java DB"上右键 –> 选择" ...

  8. ThinkPHP函数详解:U方法

    U方法用于完成对URL地址的组装,特点在于可以自动根据当前的URL模式和设置生成对应的URL地址,格式为:U('地址','参数','伪静态','是否跳转','显示域名');在模板中使用U方法而不是固定 ...

  9. sh7.创建yum源脚本练习

    练习1, 写一个脚本分别计算1-100,之间奇数和偶数之和 ji_sum.sh #!/bin/bash # let ..};do ] -eq ];then let sum+=I fi done ech ...

  10. android学习第一篇 基本概念

    一.   1.  Android 四大組件 Activity , Service  , BroadcastReceiver ,ContentProvider 2.  多個Activity組成棧,當前A ...