HDU 3686 Traffic Real Time Query System (图论)
HDU 3686 Traffic Real Time Query System
题目大意
给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个。
solution
显然园方树+tarjan求LCA,然后求两条边之间的点
必经的点的数量就是圆点的数量,然后进行分类讨论
- 若\(LCA\)为圆点:
那么其中一个点到\(LCA\)的圆点数量为\((deep[x] - deep[lca])/2\),因为\(LCA\)为圆点被算了两遍,所以要-1 - 若\(LCA\)为方点:
那么其中一个点到\(LCA\)的圆点数量为\((deep[x] - deep[lca]- 1)/2\),那么两个点之间的圆点数量就是\((deep[x] + deep[y] - 2 * deep[lca])- 1\)
由此可见,两种情况算下来,答案的式子是一样的,所以直接上板子算答案就行了,这道题的代码还是比较考验码力的……
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define v e[i].to
const int maxn=10000+3,maxe=100000+3;
int n,m,tot,head[maxn],h[2*maxn],js,dfs_clock,deep[2*maxn],father[2*maxn];
int bcc_cnt,sta[maxn],top,dfn[maxn],low[maxn];
bool vis[2*maxn];
struct edge{
int from,to,next;
}e[2*maxe],ed[2*maxe];
inline void Add(int a,int b){//原图
e[++tot].from=a;
e[tot].to=b;
e[tot].next=head[a];
head[a]=tot;
}
inline void Add2(int a,int b){//圆方树
ed[++js].from=a;
ed[js].to=b;
ed[js].next=h[a];
h[a]=js;
}
inline void tarjan(int u){
low[u]=dfn[u]=++dfs_clock;
sta[++top]=u;
for(int i=head[u];i;i=e[i].next){
if(dfn[v]) low[u]=min(low[u],dfn[v]);
else{
tarjan(v);
low[u]=min(low[v],low[u]);
if(low[v]==dfn[u]){
++bcc_cnt;
int temp;
do{
temp=sta[top];
top--;
Add2(n+bcc_cnt,temp);
Add2(temp,n+bcc_cnt);
}while(temp!=v);
Add2(u,n+bcc_cnt);
Add2(n+bcc_cnt,u);
}
}
}
}
inline void init(){
tot=0; js=0; top=0; dfs_clock=0; bcc_cnt=0;
memset(head,0,sizeof(head));
memset(e,0,sizeof(e));
memset(h,0,sizeof(h));
memset(ed,0,sizeof(ed));
memset(sta,0,sizeof(sta));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(deep,0,sizeof(deep));
memset(vis,0,sizeof(vis));
memset(father,0,sizeof(father));
memset(sta,0,sizeof(sta));
}
inline void dfs(int x){
vis[x]=1;
for(int i=h[x];i;i=ed[i].next){
int now=ed[i].to;
if(vis[now]) continue;
deep[now]=deep[x]+1;
father[now]=x;
dfs(now);
}
}
inline int find(int a,int b){//非倍增也可
if(deep[a]<deep[b]) swap(a,b);
while(deep[a]>deep[b]) a=father[a];
while(a!=b){
a=father[a];
b=father[b];
}
return a;
}
inline int len(int a,int b){
int lca=find(a,b);
return (deep[a]+deep[b]-2*deep[lca])/2-1;
}
int main(){
while(1){
scanf("%d%d",&n,&m);
if(n==0&&m==0) return 0;
init();
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
Add(x,y);
Add(y,x);
}
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n+bcc_cnt;i++) if(!vis[i]) dfs(i);
int t;
scanf("%d",&t);
while(t--){
int x,y;
scanf("%d%d",&x,&y);
int a=e[x*2].from,b=e[x*2].to,c=e[y*2].from,d=e[y*2].to; //枚举节点
printf("%d\n",max(max(len(b,d),len(a,d)),max(len(b,c),len(a,c))));
}
}
}
提交语言GCC、GCC、GCC!!!
md重要的事情说三遍,淦……
HDU 3686 Traffic Real Time Query System (图论)的更多相关文章
- 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 ...
- hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA。这题有重边!!!
http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能 ...
- HDU 3686 Traffic Real Time Query System(点双连通)
题意 给定一张 \(n\) 个点 \(m\) 条边的无向图,\(q\) 次询问,每次询问两边之间的必经之点个数. 思路 求两点之间必经之边的个数用的是边双缩点,再求树上距离.而对比边双和点双之 ...
- 【HDOJ】3686 Traffic Real Time Query System
这题做了几个小时,基本思路肯定是求两点路径中的割点数目,思路是tarjan缩点,然后以割点和连通块作为新节点见图.转化为lca求解.结合点——双连通分量与LCA. /* 3686 */ #includ ...
- 【Targan+LCA】HDU 3686 Traffic Real Time Query
题目内容 洛谷链接 给出一个\(n\)个节点,\(m\)条边的无向图和两个节点\(s\)和\(t\),问这两个节点的路径中有几个点必须经过. 输入格式 第一行是\(n\)和\(m\). 接下来\(m\ ...
- CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System
逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...
- 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 ...
- Traffic Real Time Query System 圆方树+LCA
题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...
- Traffic Real Time Query System HDU - 3686
https://vjudge.net/problem/HDU-3686 点双啊,就是在求割顶的时候,另外用一个栈来存一些边 在遍历u点出发的边时,遇到树边或反向边(u,v)就把此边加入栈(可能要记一下 ...
随机推荐
- 「从零单排canal 01」 canal 10分钟入门(基于1.1.4版本)
1.简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据 订阅 和 消费.应该是阿里云DTS(Data Transfer Servi ...
- opencl(6)读写传输命令、内存映射命令
1:将缓存对象的内容读到缓存对象中(从设备到主机) cl_int clEnqueuReadBuffer( cl_command_queue command_queue, //命令队列 cl_mem b ...
- repo 导出本地 git tag 给他人
背景 使用 repo 管理了多个 git 仓库,有时需要将本地仓库的tag同步给其他人,但又不能直接推到远程(例如权限问题). 实际场景举例 本地复现了一个问题,需要让其他人回退到相同环境来排查. 本 ...
- 一文讲透Java序列化
本文目录 一.序列化是什么 二.为什么需要序列化 三.序列化怎么用 四.序列化深度探秘 4.1 为什么必须实现Serializable接口 4.2 被序列化对象的字段是引用时该怎么办 4.3 同一个对 ...
- Python3.7解释器+sublime Text3编辑器+案例打包软件+Python语言程序设计基础教材
编辑器:https://nsyw.lanzous.com/i7lcdyh Python3.7 https://nsyw.lanzous.com/i7a299c 案例 https://nsyw.lanz ...
- web开发网络请求到数据的整合办法
开发中向服务器请求到的数据是特别复杂的,需要从中抽离出需要展示的数据进行展示个和交互. 思路: 先将请求到的复杂数据传递到一个类A中,从类A里抽离出需要的数据.需要展示数据的地方,面向类A开发,类A关 ...
- mysql索引小总结
MySql 1.索引 mysql索引默认使用的是B+Tree(B-树的变种版).也可以使用HASH表. 二叉树: 二叉树又称二叉搜索树,二叉排序树,特点如下: 左子树上所有结点值均小于根结点 右子树上 ...
- 附016.Kubernetes_v1.17.4高可用部署
一 kubeadm介绍 1.1 概述 参考<附003.Kubeadm部署Kubernetes>. 1.2 kubeadm功能 参考<附003.Kubeadm部署Kubernetes& ...
- Windows程序设计(2) -API-01 初识
Windows 程序原理 一,CPU的保护模式和windows操作系统 [x] windows 是多任务实现 [x] 虚拟内存和 各个进程的地址空间安排:2G系统空间,2G用户空间,2G用户空间是各个 ...
- Mybatis框架-CRUD
1 2 3 传统dao开发实现CRUD 3.1 传统dao开发实现crud 使用 Mybatis 开发 Dao,通常有两个方法,即原始 Dao开发方式和 Mapper 接口代理开发方式.而 ...