zoukankan      html  css  js  c++  java
  • Traffic Real Time Query System-(点双缩点+LCA)

    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;
    }
    
  • 相关阅读:
    【2018.05.05 C与C++基础】C++中的自动废料收集:概念与问题引入
    【2018.04.27 C与C++基础】关于switch-case及if-else的效率问题
    【2018.04.19 ROS机器人操作系统】机器人控制:运动规划、路径规划及轨迹规划简介之一
    March 11th, 2018 Week 11th Sunday
    March 10th, 2018 Week 10th Saturday
    March 09th, 2018 Week 10th Friday
    March 08th, 2018 Week 10th Thursday
    March 07th, 2018 Week 10th Wednesday
    ubantu之Git使用
    AMS分析 -- 启动过程
  • 原文地址:https://www.cnblogs.com/Lour688/p/12840781.html
Copyright © 2011-2022 走看看