• 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;
    }
    
  • 相关阅读:
    html5 返回当前地理位置的坐标点(经纬度)
    C#趣味程序---百鸡百钱
    Android开发:怎样隐藏自己的app应用
    Android Studio一些简单设置
    集群通信组件tribes之集群的消息接收通道
    Java基础实例
    如何用webbrowser获取ajax动态生成的网页的源码?
    phantomjs 下拉滚动条获取网页的全部源码
    Nodejs+定时截图+发送邮件
    关注网页的更新状况,了解最新的handsup 消息.
  • 原文地址:https://www.cnblogs.com/Lour688/p/12840781.html
Copyright © 2020-2023  润新知