【JZOJ】【并查集】【dfs】Idiot 的间谍网络

L i n k Link

J Z O J JZOJ 3910 3910

D e s c r i p t i o n Description

在这里插入图片描述

I n p u t Input

第一行两个正整数n 和m,分别表示间谍网络中的特工总数,以及事件的总数。
接下来m 行,第i 行给出第i 个事件的信息,格式及含义参见题面。

O u t p u t Output

输出共t 行,其中t 表示询问的总数。第i 行输出”Y ES” 或者”NO”,表示第i 次询问的答案。

S a m p l e Sample I n p u t Input

6 12
2 1
1 4 1
3 4 1
1 3 4
2 3
3 4 1
2 3
3 4 2
3 1 1
3 1 3
3 1 2
1 2 4

S a m p l e Sample O u t p u t Output

NO
NO
YES
YES
YES
YES

H i n t Hint

T r a i n Train o f of T h o u g h t Thought

C o d e Code

#include<algorithm>
#include<iostream>
#include<cstdio>

using namespace std;

bool havefa[500005], ans[500005];
int t, kk, tt;
int n, m, type[500005], x[500005], y[500005];
int father[500005], in[500005], h[500005], out[500005];

struct node
{
	int to, next;
}e[500005];

struct read
{
	int num, numb, person; 
}k[500005];

void dfs(int xx)
{
	in[xx] = ++in[0];
	for (int i = h[xx]; i; i = e[i].next)
		dfs(e[i].to);
	out[xx] = ++out[0];
}//求dfs序(用于判断一个点是否是另一个点的祖先)

bool cmp(read i, read j)
{return i.num < j.num;}

int find(int x)
{
	if (father[x] == x) return x;
	 else return father[x] = find(father[x]);
}//并查集

int main()
{
	int ttt = 0; 
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; ++i)
	{
		scanf("%d", &type[i]);
		if (type[i] == 1) {
			scanf("%d%d", &x[i], &y[i]);
			e[++t] = (node){x[i], h[y[i]]}; h[y[i]] = t;
			havefa[x[i]] = 1;//找出根节点
		} 
		 else if (type[i] == 2)	scanf("%d", &x[i]);
		  else {
		  	scanf("%d%d", &x[i], &y[i]);
		  	k[++kk] = (read) {y[i], ++ttt, x[i]};
		  }
	}
	for (int i = 1; i <= n; ++i) father[i] = i;
	for (int i = 1; i <= n; ++i) {
	 if (havefa[i] == 0) {
	 	dfs(i);
	 }
	} 
	sort(k + 1, k + kk + 1, cmp);
	int numb = 0, now = 1;
	for (int i = 1; i <= m; ++i)
	{
		if (type[i] == 1) father[find(x[i])] = find(y[i]);
		 else if (type[i] == 2) { 
			numb++;
		 	while (now <= kk && k[now].num <= numb)
		 	{
		 		if (find(k[now].person) == find(x[i]) && in[x[i]] >= in[k[now].person] && out[x[i]] <= out[k[now].person])//判断是否联通且是否是它祖先
		 		 ans[k[now].numb] = 1;
			    now++;
			 }
		 }
	}
	for (int i = 1; i <= kk; ++i)
		if (ans[i]) printf("YES\n");
		 else printf("NO\n");
}

猜你喜欢

转载自blog.csdn.net/LTH060226/article/details/103539205
今日推荐