边的双联通+缩点+LCA(HDU3686)
Traffic Real Time Query System
and each road connects two crossings. All roads are bidirectional. One of the important tasks of RTQS is to answer some queries about route-choice problem. Specifically, the task is to find the crossings which a driver MUST pass when he is driving from one
given road to another given road.
For each test case:
The first line contains two integers N and M, representing the number of the crossings and roads.
The next M lines describe the roads. In those M lines, the ith line (i starts from 1)contains two integers Xi and Yi, representing that roadi connects crossing Xi and Yi (Xi≠Yi).
The following line contains a single integer Q, representing the number of RTQs.
Then Q lines follows, each describing a RTQ by two integers S and T(S≠T) meaning that a driver is now driving on the roads and he wants to reach roadt . It will be always at least one way from roads to roadt.
The input ends with a line of “0 0”.
Please note that: 0<N<=10000, 0<M<=100000, 0<Q<=10000, 0<Xi,Yi<=N, 0<S,T<=M
#include"string.h"
#include"stdio.h"
#include"iostream"
#include"queue"
#include"stack"
#define M 10009
#define N 100009
#include"stdlib.h"
#include"math.h"
#define inf 99999999
using namespace std;
struct node//构建原图
{
int u,v,next,vis;
}edge[N*];
stack<int>q;
int t,head[M],dfn[M],low[M],cut[M],use[N*],index,num,belong[N*];
struct Tree//缩点后的图
{
int v;
Tree(){}
Tree(int vv):v(vv){}
};
vector<Tree>Edge[M+N];
void init()
{
t=;
memset(head,-,sizeof(head));
memset(edge,,sizeof(edge));
}
void add(int u,int v)//原图建边
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++index;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].vis)continue;
edge[i].vis=edge[i^].vis=;
q.push(i);
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])//求割点
{
num++;
cut[u]++;
int j;//求边联通块
do
{
j=q.top();
q.pop();
belong[j]=belong[j^]=num;//形成边连通块
}while(j!=i);
}
}
else
low[u]=min(low[u],dfn[v]);
}
if(fa<)
cut[u]--;
}
void solve(int n)
{
index=num=;
memset(dfn,,sizeof(dfn));
memset(cut,,sizeof(cut));
for(int i=;i<=n;i++)
if(!dfn[i])
tarjan(i,-);
}
struct LCA
{
int u,v,w,next;
}lca[N*];
int t1,head1[N*],f[N*],dis[N*];
void Init()
{
t1=;
memset(head1,-,sizeof(head1));
}
void Addlca(int u,int v)
{
lca[t1].u=u;
lca[t1].v=v;
lca[t1].next=head1[u];
head1[u]=t1++;
}
int finde(int x)
{
if(x!=f[x])
f[x]=finde(f[x]);
return f[x];
}
void make(int a,int b)
{
f[finde(a)]=finde(b);
}
void dfs(int u)//离线LCA算法
{
use[u]=;
for(int i=;i<(int)Edge[u].size();i++)
{
int v=Edge[u][i].v;
if(!use[v])
{
dis[v]=dis[u]+;
dfs(v);
f[v]=u;
make(u,v);
}
}
for(int i=head1[u];i!=-;i=lca[i].next)
{
int v=lca[i].v;
if(use[v])
lca[i].w=lca[i^].w=f[finde(v)];
}
}
void slove()
{
dis[]=;
for(int i=;i<=num;i++)
f[i]=i;
memset(use,,sizeof(use));
for(int i=;i<=num;i++)
if(!use[i])
dfs(i);
for(int i=;i<t1;i+=)
{
int u=lca[i].u;
int v=lca[i].v;
int mid=lca[i].w;
printf("%d\n",(dis[u]+dis[v]-*dis[mid])/);
}
}
int main()
{
int n,m,i,u,v;
while(scanf("%d%d",&n,&m),m||n)
{
init();
for(i=;i<m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
solve(n);//求割点和边联通块
memset(use,,sizeof(use));
for(u=;u<=n;u++)
{
if(cut[u])
{
++num;//在边的联通块的序号之上继续给割点编号
for(i=head[u];i!=-;i=edge[i].next)
{
if(!use[belong[i]])//某个割点和相邻某条边建边后即与边联通块连接,应该去重
{
Edge[num].push_back(belong[i]);
Edge[belong[i]].push_back(num);
use[belong[i]]=;
}
}
for(i=head[u];i!=-;i=edge[i].next)
use[belong[i]]=;
}
}
int Q;
scanf("%d",&Q);
Init();
while(Q--)
{
scanf("%d%d",&u,&v);//输入的是原始边的排列序号
Addlca(belong[u*-],belong[v*-]);//把边映射到边联通块中
Addlca(belong[v*-],belong[u*-]);
}
slove();
for(i=;i<=num;i++)
Edge[i].clear();
}
}
边的双联通+缩点+LCA(HDU3686)的更多相关文章
- poj 3694双联通缩点+LCA
题意:给你一个无向连通图,每次加一条边后,问图中桥的数目. 思路:先将图进行双联通缩点,则缩点后图的边就是桥,然后dfs记录节点深度,给出(u,v)使其节点深度先降到同一等级,然后同时降等级直到汇合到 ...
- hdu 4612 双联通缩点+树形dp
#pragma comment(linker,"/STACK:102400000,102400000")//总是爆栈加上这个就么么哒了 #include<stdio.h> ...
- 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 ...
- Codeforces 1000 组合数可行线段倒dp 边双联通缩点求树直径
A /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std ...
- POJ3694 Network(边双连通分量+缩点+LCA)
题目大概是给一张图,动态加边动态求割边数. 本想着求出边双连通分量后缩点,然后构成的树用树链剖分+线段树去维护路径上的边数和..好像好难写.. 看了别人的解法,这题有更简单的算法: 在任意两点添边,那 ...
- 图论-桥/割点/双连通分量/缩点/LCA
基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...
- lightoj 1291 无向图边双联通+缩点统计叶节点
题目链接:http://lightoj.com/volume_showproblem.php?problem=1291 #include<cstdio> #include<cstri ...
- BZOJ1123 [POI2008]BLO(割点判断 + 点双联通缩点size)
#include <iostream> #include <cstring> #include <cstdio> using namespace std; type ...
- hdu 2460 poj 3694 (双联通+LCA)
在给出的两个点上加一条边,求剩下桥的数量,,不会LCA在线,就用了最普通的,先Tarjan双联通缩点,然后将缩完的图建成一棵树,树的所有边就是桥了,如果在任意两点间加一条边的话,那么从两点到最近公共祖 ...
随机推荐
- Python 变量类型和运算符
-*- coding:utf-8 -*- ''' if语法 if conditon: [tab键] command [tab键] command ... else: [tab键] command [t ...
- Latex的各种帽子
\hat{A} \widehat{A} \tilde{A} \widetilde{A} \overline{A} \underline{A} \overbrace{A} \underbrace{A} ...
- DOM编程 学习笔记(一)
PS:虽然自己JS基本语法算是掌握了,但是其实在JS掌握的只是远远还不够,网页上有太多好看的动态效果都是用JS 做出来的,自己也就仅仅会那么一两个动态的效果,学的只是皮毛...等有空的时候一定要好好的 ...
- CentOS 7修改MySQL 5.6字符集为UTF-8
MySQL编码原因会导致数据库出现中文乱码 解决办法: 修改MySQL数据库字符编码为UTF-8,UTF-8包含全世界所有国家需要用到的字符,是国际编码. 具体操作: 1.进入MySQL控制台 mys ...
- API Design Principles -- QT Project
[the original link] One of Qt’s most reputed merits is its consistent, easy-to-learn, powerfulAPI. T ...
- pyqt二进制和图片的转换
参考:http://blog.chinaunix.net/uid-28194872-id-3516936.html MySQL数据库要想插入图片,其字段需要是BLOB类型.BLOB (binary l ...
- mysql分组取每组大的记录
SELECT a.* FROM chat_log a INNER JOIN (SELECT MAX(id) id,to_user FROM chat_log GROUP BY to_user)b ON ...
- Sqlserver2005:深入了解php执行sqlserver存储过程procedure:odbc_exe、odbc_execute
以下存储过程(伪代码): -- 伪代码,假设相关操作是成功的 alter procedure pr_test as begin set nocount on update tab set col='n ...
- ChemOffice Professional 16.0新增了哪些功能
ChemOffice Professional 16.0是为终极化学和生物组件设计,可满足化学家和生物学家的需求.ChemOffice Professional帮助科学家有效地检索数据库,包括SciF ...
- three.js obj转js
js格式的模型文件是three.js中可以直接加载的文件.使用THREE.JSONLoader()直接加载,而不需要引用其它的loader插件. obj格式转js格式使用的是threejs.org官方 ...