• CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System


    题目描述

    现代社会,路是必不可少的。任意两个城镇都有路相连,而且往往不止一条。但有些路连年被各种XXOO,走着很不爽。按理说条条大路通罗马,大不了绕行其他路呗——可小撸却发现:从a城到b城不管怎么走,总有一些逃不掉的必经之路

    他想请你计算一下,a到b的所有路径中,有几条路是逃不掉的?

    输入格式

    第一行是n和m,用空格隔开。接下来m行,每行两个整数x和y,用空格隔开,表示x城和y城之间有一条长为1的双向路。第m+2行是q。接下来q行,每行两个整数a和b,用空格隔开,表示一次询问。

    输出格式

    对于每次询问,输出一个正整数,表示a城到b城必须经过几条路。

    样例输入

    5 5
    1 2
    1 3
    2 4
    3 4
    4 5
    2
    1 4
    2 5

    样例输出

    0
    1

    样例解释

    第1次询问,1到4的路径有 1--2--4 ,还有 1--3--4 。没有逃不掉的道路,所以答案是0。
    第2次询问,2到5的路径有 2--4--5 ,还有 2--1--3--4--5 。必须走“4--5”这条路,所以答案是1。

    数据约定与范围

    共10组数据,每组10分。

    有3组数据,n ≤ 100 , n ≤ m ≤ 200 , q ≤ 100。
    另有2组数据,n ≤ 103 , n ≤ m ≤ 2 x 103 , 100 < q ≤ 105
    另有3组数据,103 < n ≤ 105 , m = n-1 , 100 < q ≤ 105
    另有2组数据,103 < n ≤ 105 , n ≤ m ≤ 2 x 105 , 100 < q ≤ 105

    对于全部的数据,1 ≤ x,y,a,b ≤ n;对于任意的道路,两端的城市编号之差不超过104
    任意两个城镇都有路径相连;同一条道路不会出现两次;道路的起终点不会相同;查询的两个城市不会相同。

    题解

    要求无向图的必经边,较为简单的做法是找出边双缩点,然后转化成树上距离问题。

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;rg char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
        for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
        return data*w;
    }
    template<class T>il T read(rg T&x) {return x=read<T>();}
    typedef long long ll;
    using namespace std;
    
    co int N=2e5+1;
    int n,m;
    int head[N],ver[N*2],next[N*2],tot=1;
    int dfn[N],low[N],c[N],num,dcc;
    bool bridge[N*2];
    int hc[N],vc[N*2],nc[N*2],tc=1;
    int d[N],f[N][18];
    queue<int> q;
    
    il void add(int x,int y){
    	ver[++tot]=y,::next[tot]=head[x],head[x]=tot;
    }
    il void add_c(int x,int y){
    	vc[++tc]=y,nc[tc]=hc[x],hc[x]=tc;
    }
    void tarjan(int x,int in_edge){
    	dfn[x]=low[x]=++num;
    	for(int i=head[x];i;i=::next[i]){
    		int y=ver[i];
    		if(!dfn[y]){
    			tarjan(y,i);
    			low[x]=min(low[x],low[y]);
    			if(low[y]>dfn[x]) bridge[i]=bridge[i^1]=1;
    		}
    		else if(i!=(in_edge^1)) low[x]=min(low[x],dfn[y]);
    	}
    }
    void dfs(int x){ // dye
    	c[x]=dcc;
    	for(int i=head[x];i;i=::next[i]){
    		int y=ver[i];
    		if(c[y]||bridge[i]) continue;
    		dfs(y);
    	}
    }
    void bfs(){
    	
    }
    int lca(int x,int y){
    	if(d[x]<d[y]) swap(x,y);
    	for(int i=17;i>=0;--i)
    		if(d[f[x][i]]>=d[y]) x=f[x][i];
    	if(x==y) return x;
    	for(int i=17;i>=0;--i)
    		if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    int main(){
    	read(n),read(m);
    	for(int x,y;m--;){
    		read(x),read(y);
    		add(x,y),add(y,x);
    	}
    // 缩点建图
    	for(int i=1;i<=n;++i)
    		if(!dfn[i]) tarjan(i,0);
    	for(int i=1;i<=n;++i)
    		if(!c[i]) ++dcc,dfs(i);
    	for(int i=2;i<=tot;++i){
    		int x=ver[i^1],y=ver[i];
    		if(c[x]!=c[y]) add_c(c[x],c[y]);
    	}
    // 倍增lca预处理
    	d[1]=1,q.push(1);
    	while(q.size()){
    		int x=q.front();q.pop();
    		for(int i=hc[x];i;i=nc[i]){
    			int y=vc[i];
    			if(d[y]) continue;
    			d[y]=d[x]+1,f[y][0]=x;
    			for(int j=1;j<18;++j) f[y][j]=f[f[y][j-1]][j-1];
    			q.push(y);
    		}
    	}
    // 处理询问
    	read(m);
    	for(int x,y;m--;){
    		x=c[read<int>()],y=c[read<int>()];
    		printf("%d
    ",d[x]+d[y]-2*d[lca(x,y)]);
    	}
    	return 0;
    }
    

    Traffic Real Time Query System

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 3808    Accepted Submission(s): 759


    Problem Description
    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 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
     

    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
     

    Source
     

    Recommend
    lcy&zhengfeng   |   We have carefully selected several similar problems for you:  3689 3682 3683 3681 3687 
     

    给你一个无向图,询问边a和边b,问从边a到边b的路径中几个点是必须要经过的。

    题解

    求无向图的必经点,跟上题类似,求出点双后缩点,然后转化成查询路径上割点的个数。由于点双缩点的特殊性,所以算距离的时候写的不一样。

    #include<iostream>
    #include<cstring>
    #include<queue>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;rg char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
        for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
        return data*w;
    }
    template<class T>il T read(rg T&x) {return x=read<T>();}
    typedef long long ll;
    using namespace std;
    
    co int N=2e4+1,M=2e5+2;
    int n,m,t;
    int head[N],ver[M],next[M],tot;
    int dfn[N],low[N],stack[N],new_id[N],c[N],belong[M],num,root,top,cnt;
    int d[N],dist[N],f[N][16];
    bool cut[N];
    vector<int> dcc[N];
    int hc[N],vc[M],nc[M],tc;
    queue<int> q;
    
    il void add(int x,int y){
    	ver[++tot]=y,::next[tot]=head[x],head[x]=tot;
    }
    il void add_c(int x,int y){
    	vc[++tc]=y,nc[tc]=hc[x],hc[x]=tc;
    }
    void tarjan(int x){
    	dfn[x]=low[x]=++num;
    	stack[++top]=x;
    	if(x==root&&head[x]==0){
    		dcc[++cnt].push_back(x);
    		return;
    	}
    	int flag=0;
    	for(int i=head[x];i;i=::next[i]){
    		int y=ver[i];
    		if(!dfn[y]){
    			tarjan(y);
    			low[x]=min(low[x],low[y]);
    			if(low[y]>=dfn[x]){
    				++flag;
    				if(x!=root||flag>1) cut[x]=1;
    				++cnt;
    				int z;
    				do{
    					z=stack[top--];
    					dcc[cnt].push_back(z);
    				}while(z!=y);
    				dcc[cnt].push_back(x);
    			}
    		}
    		else low[x]=min(low[x],dfn[y]);
    	}
    }
    void bfs(int s){
    	d[s]=1,dist[s]=s>cnt,q.push(s);
    	for(int i=0;i<16;++i) f[s][i]=0;
    	while(q.size()){
    		int x=q.front();q.pop();
    		for(int i=hc[x];i;i=nc[i]){
    			int y=vc[i];
    			if(d[y]) continue;
    			d[y]=d[x]+1,dist[y]=dist[x]+(y>cnt),f[y][0]=x;
    			for(int j=1;j<16;++j) f[y][j]=f[f[y][j-1]][j-1];
    			q.push(y);
    		}
    	}
    }
    int lca(int x,int y){
    	if(d[x]<d[y]) swap(x,y);
    	for(int i=15;i>=0;--i)
    		if(d[f[x][i]]>=d[y]) x=f[x][i];
    	if(x==y) return x;
    	for(int i=15;i>=0;--i)
    		if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    int main(){
    	while(read(n)|read(m)){
    		memset(head,0,sizeof head);
    		memset(hc,0,sizeof hc);
    		memset(dfn,0,sizeof dfn);
    		memset(d,0,sizeof d);
    		memset(cut,0,sizeof cut);
    		memset(c,0,sizeof c);
    		for(int i=1;i<=n;++i) dcc[i].clear();
    		tot=1,num=cnt=top=0;
    		for(int x,y;m--;){
    			read(x),read(y);
    			add(x,y),add(y,x);
    		}
    		for(int i=1;i<=n;++i)
    			if(!dfn[i]) root=i,tarjan(i);
    		num=cnt;
    		for(int i=1;i<=n;++i)
    			if(cut[i]) new_id[i]=++num;
    		tc=1;
    		for(int i=1;i<=cnt;++i){
    			for(int j=0;j<dcc[i].size();++j){
    				int x=dcc[i][j];
    				if(cut[x]) add_c(i,new_id[x]),add_c(new_id[x],i);
    				c[x]=i;
    			}
    			for(int j=0;j<dcc[i].size()-1;++j){
    				int x=dcc[i][j];
    				for(int k=head[x];k;k=::next[k]){
    					int y=ver[k];
    					if(c[y]==i) belong[k/2]=i; // 输入的第k/2条边(x,y)处于第i个v-DCC内
    				}
    			}
    		}
    		// 编号 1~cnt 的为原图的v-DCC,编号 cnt+1~num 的为原图割点
    		for(int i=1;i<=num;++i)
    			if(!d[i]) bfs(i);
    		read(t);
    		while(t--){
    			int es=read<int>(),et=read<int>();
    			int x=belong[es],y=belong[et],z=lca(x,y);
    			printf("%d
    ",dist[x]+dist[y]-2*dist[z]+(z>cnt));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    PPT 转 word
    securefx 系统中不到指定文件 (转中文)
    U盘使用技巧篇 制作一般人删除不了的文件(宣传视频) (量产开卡)
    电脑加载有文件的CD、DVD驱动器图标修改
    CentOS 7 网卡注释
    linux IP 注释
    VMware虚拟机安装黑群晖DSM6.2 (转)
    DAS、SAN和NAS三种服务器存储方式 (转)
    wdCP V3.2
    JS异步编程 XHR的用法
  • 原文地址:https://www.cnblogs.com/autoint/p/11046847.html
Copyright © 2020-2023  润新知