首页 > 代码库 > ZOJ 3811 Untrusted Patrol bfs+并查集

ZOJ 3811 Untrusted Patrol bfs+并查集

题目链接:点击打开链接

题意:

给定n个点m条边的无向图,k个触发器。

下面k个数表示触发器安装在哪几个点。

下面m行给出边

最后有l个信号,

给出信号发出的触发器的顺序。

每个触发器只会发出一次信号,且一个点只有一个触发器。

有一个人在遍历图。

每经过一个点,那个点的触发器就会发出信号,问是否存在一种走法使得这个人遍历了所有点且触发器发出的信号顺序和给出的一样。

思路:

先把无触发器的点放到图里。

然后根据触发器的信号顺序把点依次加入图中,加入时只添加(与无触发器点相连的边)

然后判断这个点能否与之前的图连通。bfs+并查集判断。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include <queue>
using namespace std;
#define ll int
typedef pair<int,int> pii;
#define M 400010
#define N 200010
int f[N];
int find(int x){return x==f[x]?x:f[x] = find(f[x]);}
void Union(int x,int y){
	int fx = find(x), fy = find(y);
	if(fx==fy)return ;
	if(fx>fy)swap(fx,fy);
	f[fx] = fy;
}
struct Edge{
	int from, to, nex;
}edge[M<<1];
int head[N], edgenum;
void init(){memset(head, -1, sizeof head); edgenum = 0;}
void add(int u, int v){
	Edge E = {u, v, head[u]};
	edge[edgenum] = E;
	head[u] = edgenum++;
}
int n, m, k, l;
int is[N], vis[N];
vector<int>G, E[N];
void ADD(int x){
	for(int i = 0; i < E[x].size(); i++){
		if(is[E[x][i]] == 0)
		add(x, E[x][i]);
	}
	is[x] = 0;
}
void bfs(int x){
	queue<int>q; q.push(x);
	vis[x] = 1;
	while(!q.empty()){
		int u = q.front(); q.pop();
		for(int i = head[u]; ~i; i = edge[i].nex)
		{
			int v = edge[i].to;
			Union(v, x);
			if(vis[v])continue;
			vis[v] = 1;
			q.push(v);
		}
	}
}
bool solve(){
	scanf("%d %d %d",&n,&m, &k);
	init();
	int i, j, u, v;
	for(i = 1; i <= n; i++) {
		vis[i] = is[i] = 0;
		E[i].clear();
	}
	for(i = 1; i <= k; i++) { scanf("%d",&j); is[j] = 1; }
	while(m--){
		scanf("%d %d", &u, &v);
		E[u].push_back(v); E[v].push_back(u);
	}
	G.clear();
	scanf("%d", &l);
	for(i = 1; i <= l; i++) { scanf("%d", &j); G.push_back(j); }
	//若触发器没有全响,就不行
	if(k!=l)return false;
	//若没有触发器一定可以。
	if(k == 0) return true;
	for(i = 1; i <= n; i++)
	{
		if(is[i] == 0)
		{
			for(j = 0; j < E[i].size(); j++)
				if(is[E[i][j]]==0)
					add(i, E[i][j]);
		}
	}
	for(i = 1; i <= n; i++) f[i] = i;
	for(i = 0; i < G.size(); i++) {
		u = G[i];
		ADD(u);
		bfs(u);
		if(i-1>=0){
			find(G[i]); find(G[i-1]);
			if(f[G[i]] != f[G[i-1]])
				return false;
		}
	}
	for(i = 1; i <= n; i++) if(vis[i] == 0) return false;
	return true;
}
int main(){
	int T; scanf("%d",&T);
	while(T--)
		solve() ? puts("Yes"):puts("No");
	return 0;
}
/*
99
5 5 3
1 2 4
1 2
2 3
3 1
1 4
4 5
3
4 2 1
5 5 3
1 2 4
1 2
2 3
3 1
1 4
4 5
3
4 1 2

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

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

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

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

ans:
N
Y
Y
Y
N
N

*/


ZOJ 3811 Untrusted Patrol bfs+并查集