// [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; }
并查集 + Bfs 之 zoj 3811 Untrusted Patrol
最新推荐文章于 2015-08-18 10:37:29 发布