Traffic Real Time Query System
City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, the mayor plans to build a RTQS (Real Time Query System) to monitor all traffic situations. City C is made up of N crossings and M roads, 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.
Input
There are multiple test cases.
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 i th line (i starts from 1)contains two integers X i and Y i, representing that road i connects crossing X i and Y i (X i≠Y i).
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<X i,Y i<=N, 0<S,T<=M
Output
For each RTQ prints a line containing a single integer representing the number of crossings which the driver MUST pass.
Sample Input
5 6
1 2
1 3
2 3
3 4
4 5
3 5
2
2 3
2 4
0 0
Sample Output
0
1
一个城市有n个路口,m条无向公路。求从第S条路到第T条路必须经过的点有几个。
Solution
挺明显的点双缩点,但最后找必经点的时候要用LCA,
首先必经过的一定是割点(问的是必经点嘛),因此可以先做点双连通然后缩点 缩完点后形成了树 ,这样的模式的u->v只要走一步,那就必经一个割点,路径u->v只需要求出他们的lca 则答案可以通过(dis[u]+dis[v]-dis[lca]*2)/2算出.
(代码好好调吧......)
Code
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
typedef long long LL;
const int maxn=2e4+5,maxm=4e5+5;
int n,m,q,tot,idx,top;
int fu[maxm],fv[maxm];
int head[maxn],dfn[maxn],low[maxn],belong[maxm],st[maxm],tmp[maxn];
int vis[maxn],dis[maxn],lca[maxn][20];
struct Edge{int u,v,next;bool fg;}e[maxm];
pair<int,int> E[maxm];
void Init(){
tot=0;idx=0;top=0;
memset(head,-1,sizeof head);
memset(dfn,0,sizeof dfn);
memset(tmp,0,sizeof tmp);
memset(vis,0,sizeof vis);
}
void Add(int x,int y){
e[tot].u=x;
e[tot].v=y;
e[tot].fg=0;
e[tot].next=head[x];
head[x]=tot++;
}
void Tarjan(int u,int fa){
dfn[u]=low[u]=++idx;
int j,v;
for(int i=head[u];~i;i=e[i].next){
v=e[i].v;
if(e[i].fg||dfn[v]>=dfn[u])continue;
e[i].fg=e[i^1].fg=1;
st[++top]=i;
if(!dfn[v]){
Tarjan(v,u);
low[u]=min(low[u],low[v]);
if(dfn[u]<=low[v]){
n++;
do{
j=st[top--];
if(tmp[e[j].v]!=n){
E[m++]=make_pair(n,e[j].v);
tmp[e[j].v]=n;
}
if(tmp[e[j^1].v]!=n){
E[m++]=make_pair(n,e[j^1].v);
tmp[e[j^1].v]=n;
}
belong[j>>1]=n;
}while(j!=i);
}
}else low[u]=min(low[u],dfn[v]);
}
}
void Mktb(int u,int from){
vis[u]=1;
dis[u]=dis[from]+1;
lca[u][0]=from;
for(int i=1;i<20;++i)lca[u][i]=lca[lca[u][i-1]][i-1];
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;
if(v!=from&&!vis[v])Mktb(v,u);
}
}
void Swap(int &a,int &b){int c=a;a=b;b=c;}
int LCA(int u,int v){
if(dis[v]>dis[u])Swap(u,v);
int tm=dis[u]-dis[v];
for(int i=19;tm;i--)
if(tm>=(1<<i))tm-=(1<<i),u=lca[u][i];
if(u==v)return u;
for(int i=19;i>=0;--i)
if(lca[u][i]!=lca[v][i])u=lca[u][i],v=lca[v][i];
return lca[u][0];
}
int main(){
int u,v,f;
while(scanf("%d%d",&n,&m)!=EOF){
if(!n&&!m)return 0;
Init();
for(int i=1;i<=m;++i){
scanf("%d%d",&u,&v);
Add(u,v);Add(v,u);
fu[i]=u;fv[i]=v;
}
m=0;
for(int i=1;i<=n;++i)if(!dfn[i])Tarjan(i,i);
tot=0;
memset(head,-1,sizeof head);
for(int i=0;i<m;++i){
Add(E[i].first,E[i].second);
Add(E[i].second,E[i].first);
}
for(int i=1;i<=n;++i)if(!vis[i])Mktb(i,0);
scanf("%d",&q);
int i,j;
while(q--){
scanf("%d%d",&i,&j);
u=belong[i-1];
v=belong[j-1];
f=LCA(u,v);
printf("%d
",(dis[u]+dis[v]-dis[f]*2)>>1);
}
}
return 0;
}