列表

详情


NC20906. SSJ的梦境

描述

JSS和漂亮的QSW是来自世界不同地区的网友。(JSS是来自菲律宾的长人,漂亮的QSW是来自印度的长人,JSS很白,QSW也很白)

某一天,JSS和QSW都要从自己所在的地区出发,去往自己的目的地(两人的目的地都可能不在两人当前所在的国家),但两人的目的地不同。两个常年不见的亲密网友十分想在旅途中与对方碰面,但他们又想有小小的惊喜和希望,所以他们一起规划了旅行的路线。
包含两人的出发点在内,他们一起在地图上圈出了n个点,n个点两两可能在同一个国家也可能在不同国家。由于在贺可其老师口中,印度和菲律宾都比较不靠谱,而两个国家又十分的好面子,所以地图上国家之内的航线是单向的,而国家与国家之间的航线是双向的。但是JSS和QSW都十分怕麻烦,所以在地图上把所有m条路线画成了单向的(但并不影响国家与国家之间互相到达,并且保证国家与国家之间的航线数是国家数-1)。JSS和QSW一定能从开始时两人所在地区所处的国家出发并且如果JSS和QSW进行的是跨国旅行,他们会在国家和国家之间会选择走最短的路线。
JSS和QSW十分想知道他俩能否在旅途中相遇,所以他们把这个问题丢给了Fyy...QAQ
Fyy同样困惑,因为JSS和QSW给出的可能的出发点和终点太多了,他小小的脑子思考不过来,所以他找到了会编程的你 :) 。Fyy会给你t组询问,每组询问给你JSS和QSW的起点a、c和终点b、d,并询问你两人能否相遇。

输入描述

输入文件第一行为三个整数n,m,t分别表示n个地区和m条有向边以及t组询问。
接下来m行,每行有两个整数x和y,表示从x到y有一条有向边。
接下来t行,每行有四个整数a,b,c,d,分别表示rjx的起点和终点以及smy的起点和终点。

输出描述

输出文件共有t行,每行包含一个字符“Y”或“N”,分别表示该次询问中JSS和QSW能或不能相遇。

示例1

输入:

9 11 3
2 1
1 3
3 2
4 2
7 3
4 5
5 6
6 4
8 7
7 9
9 8
5 7 8 1
4 2 7 1
6 8 9 2

输出:

Y
Y
Y

说明:

n ≤ 10000,m≤ 200000

注意:
1. 国家内的路是有向的,国家之间的路是无向的,但数据给出的边都是有向的。

2. 只要JSS和QSW在各自的旅途中有至少一个国家是被两人都经过的就算相遇。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 623ms, 内存消耗: 21752K, 提交时间: 2020-08-15 20:14:02

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long 
using namespace std;
const int maxn=2e5+5;
int dfn[maxn],low[maxn],stack[maxn],vis[maxn],deep,top,num,s[maxn];
int n,m;

vector<int>G[maxn];
vector<int>g[maxn];
vector<int>T[maxn];

void tarjan(int u){
	dfn[u]=low[u]=++deep;
	stack[++top]=u;
	vis[u]=1;
	for (int v:G[u]){
		if (!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}else if (vis[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	
	if (low[u]==dfn[u]){
		num++;
		do{
			T[num].push_back(stack[top]);
			vis[stack[top]]=0;
			top--;
		}while (stack[top+1]!=u);

	}
}
int a[maxn],b[maxn];


int f[maxn][25], dep[maxn];
int  q;

void dfs(int now,int fa){
    dep[now]=dep[fa]+1;f[now][0]=fa;
    for(int i=1; (1<<i)<=dep[now]; i++)
        f[now][i]=f[f[now][i-1]][i-1];
        
    for(int u:g[now])
        if(u!=fa) dfs(u,now);
}

int LCA(int x, int y) {
    if(dep[x] < dep[y]) swap(x, y);
    for(int i = 22; ~i; i--) if(dep[f[x][i]] >= dep[y]) x = f[x][i];
    if(x == y) return x;
    for(int i = 22; ~i; i--) if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
    return f[x][0];
}



int main(){
	ios::sync_with_stdio(false);
	int N,M,t;
	cin>>N>>M>>t;
	for (int i=1;i<=M;i++){
		cin>>a[i]>>b[i];
		G[a[i]].push_back(b[i]);	
	}
	
	for (int i=1;i<=N;i++){
		if (!dfn[i]) tarjan(i);
	}
	
	for (int i=1;i<=num;i++){
		for (int j=0;j<T[i].size();j++){
			s[T[i][j]]=i;
		}
	}
	for (int i=1;i<=M;i++){
		if (s[a[i]]!=s[b[i]]){
			g[s[a[i]]].push_back(s[b[i]]);
			g[s[b[i]]].push_back(s[a[i]]);
		}
	}
	
	dfs(1,0);
	
	
	for (int i=0;i<t;i++){
		int a,b,c,d,lca1,lca2;
		cin>>a>>b>>c>>d;
		a=s[a];
		b=s[b];
		c=s[c];
		d=s[d];
		
		
		int p=LCA(a,b),q=LCA(c,d);
        if((dep[p]>dep[c]&&dep[p]>dep[d])||(dep[q]>dep[a]&&dep[q]>dep[b]))
        {
            puts("N");
            continue;
        }
        if(dep[p]>=dep[q])
        {
            if(LCA(p,c)==p||LCA(p,d)==p)
            {
                puts("Y");
                continue;
            }
        }
        else
        {
            if(LCA(q,a)==q||LCA(q,b)==q)
            {
                puts("Y");
                continue;
            }
        }
        puts("N");
		
	}
	
}

上一题