并查集 + Bfs 之 zoj 3811 Untrusted Patrol

来源:互联网 发布:淘宝武汉飞鱼 编辑:程序博客网 时间:2024/05/11 13:18
//  [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 能到达的传感器记录的点都已标记下来。。。*/
#include <iostream>#include <cstdlib>#include <cstdio>#include <vector>#include <queue>using namespace std;const int MAX_N = 100005;int N, M, K;vector<int> Edge[MAX_N];bool isVis[MAX_N];bool isIn[MAX_N];int verOrder[MAX_N];int father[MAX_N];void Del() {for (int i = 1; i <= N; ++i) {if (!Edge[i].empty()) {Edge[i].clear();}}}int myFind(int x) {if (x == father[x]) return x;else return father[x] = myFind(father[x]);}bool judge_Connected_Graph() {int ver = myFind(N);for (int i = 1; i < N; ++i) {if (myFind(i) != ver) {return false;}}return true;}bool Bfs() {isVis[verOrder[0]] = true;queue<int> que;for (int i = 0; i < K; ++i) {if (isVis[verOrder[i]]) que.push(verOrder[i]);else return false;while (!que.empty()) {int ver = que.front();que.pop();for (int i = 0; i < Edge[ver].size(); ++i) {int t_ver = Edge[ver][i];if (!isVis[t_ver]) {if (isIn[t_ver]) isVis[t_ver] = true;else {isVis[t_ver] = true;que.push(t_ver);}}}}}return true;}int main() {//freopen("input.txt", "r", stdin);int T;scanf("%d", &T);while (T--) {scanf("%d %d %d", &N, &M, &K);for (int i = 1; i <= N; ++i) {isIn[i] = false;isVis[i] = false;father[i] = i;}int sensor;for (int i = 0; i < K; ++i) {scanf("%d", &sensor);isIn[sensor] = true;}int u, v;for (int i = 0; i < M; ++i) {scanf("%d %d", &u, &v);Edge[u].push_back(v);Edge[v].push_back(u);int tmp1 = myFind(v);int tmp2 = myFind(u);if (tmp1 != tmp2) {father[tmp1] = tmp2;}}int sum;scanf("%d", &sum);for (int i = 0; i < sum; ++i) {scanf("%d", &sensor);verOrder[i] = sensor;}if ((sum < K) || (!judge_Connected_Graph()) || (!Bfs())) {printf("No\n");}else printf("Yes\n");Del();}return 0;}
0 0