// [9/12/2014 Sjm]
/*
此题在大神的帮助下AC了。。。
要求:output "Yes" if the security man worked normally and has checked all piles of drinks, or "No" if not.
(1)check all piles of drinks:
1) L == K (L 是 gathered from all sensors,所以若L < K,则必然是有些带有传感器的节点没有走,无法满足条件)
2) 图一定是连通,否则从一个点出发无法走遍所有节点 (通过并查集判断)
(2)worked normally:
意思巡逻的路线是可以根据图中所给的边找出来的,
而不是digs through walls, climb over piles, use some black magic to teleport to anywhere and so on.
故而需要判断能否找到一个正常的巡逻路线。。。
( 注意正常的巡逻路线是可以重复走途中所给的边,
即若A与B相连,A与C相连,则如果从A到B后,亦可从B返回A,再到C)
思路:
1)从第 K 个传感器所记录的点出发,寻找到其所有能到达的传感器所记录的点。。转向 2)
2)判断第 K+1 个传感器所记录的点,是否可由前K个传感器所记录的点所到达
若否,则即可判断正常的巡逻路线不存在。。。
若是,则 K = K + 1,不断进行操作 2),直至所有传感器的点均可被到达,可判断正常的巡逻路线存在。。。
关键:
如何用计算机去求 “从第 K 个传感器所记录的点出发,寻找到其所有能到达的传感器所记录的点”?
解法就像是自动机:
假设从点 A (此点即队列中第一个点)出发,采用 Bfs 找出该点能到达的所有点,
在这些点中,对于传感器记录的点进行标记,而对于非传感器记录的点,放到队列中,
再将队列中的点取出,继续寻找其能到达的所有点,同点 A 进行的操作处理。。
直到队列为空,则说明此时对于点 A 能到达的传感器记录的点都已标记下来。。。
*/
1 #include <iostream>
2 #include <cstdlib>
3 #include <cstdio>
4 #include <vector>
5 #include <queue>
6 using namespace std;
7 const int MAX_N = 100005;
8 int N, M, K;
9 vector<int> Edge[MAX_N];
10 bool isVis[MAX_N];
11 bool isIn[MAX_N];
12 int verOrder[MAX_N];
13 int father[MAX_N];
14
15 void Del() {
16 for (int i = 1; i <= N; ++i) {
17 if (!Edge[i].empty()) {
18 Edge[i].clear();
19 }
20 }
21 }
22
23 int myFind(int x) {
24 if (x == father[x]) return x;
25 else return father[x] = myFind(father[x]);
26 }
27
28 bool judge_Connected_Graph() {
29 int ver = myFind(N);
30 for (int i = 1; i < N; ++i) {
31 if (myFind(i) != ver) {
32 return false;
33 }
34 }
35 return true;
36 }
37
38 bool Bfs() {
39 isVis[verOrder[0]] = true;
40 queue<int> que;
41 for (int i = 0; i < K; ++i) {
42 if (isVis[verOrder[i]]) que.push(verOrder[i]);
43 else return false;
44 while (!que.empty()) {
45 int ver = que.front();
46 que.pop();
47 for (int i = 0; i < Edge[ver].size(); ++i) {
48 int t_ver = Edge[ver][i];
49 if (!isVis[t_ver]) {
50 if (isIn[t_ver]) isVis[t_ver] = true;
51 else {
52 isVis[t_ver] = true;
53 que.push(t_ver);
54 }
55 }
56 }
57 }
58 }
59 return true;
60 }
61
62 int main() {
63 //freopen("input.txt", "r", stdin);
64 int T;
65 scanf("%d", &T);
66 while (T--) {
67 scanf("%d %d %d", &N, &M, &K);
68 for (int i = 1; i <= N; ++i) {
69 isIn[i] = false;
70 isVis[i] = false;
71 father[i] = i;
72 }
73 int sensor;
74 for (int i = 0; i < K; ++i) {
75 scanf("%d", &sensor);
76 isIn[sensor] = true;
77 }
78 int u, v;
79 for (int i = 0; i < M; ++i) {
80 scanf("%d %d", &u, &v);
81 Edge[u].push_back(v);
82 Edge[v].push_back(u);
83 int tmp1 = myFind(v);
84 int tmp2 = myFind(u);
85 if (tmp1 != tmp2) {
86 father[tmp1] = tmp2;
87 }
88 }
89 int sum;
90 scanf("%d", &sum);
91 for (int i = 0; i < sum; ++i) {
92 scanf("%d", &sensor);
93 verOrder[i] = sensor;
94 }
95 if ((sum < K) || (!judge_Connected_Graph()) || (!Bfs())) {
96 printf("No
");
97 }
98 else printf("Yes
");
99 Del();
100 }
101 return 0;
102 }