ZOJ - 3811 Untrusted Patrol(bfs+并查集)
2015-03-10 21:22
429 查看
题意:
有N个城市,M条路。有K个传感器,分布在给定的K个城市中。传感器只会在第一次到达该城市时触发。现在给出L个传感器触发的先后顺序,问是否有方案遍历完所有的城市。解析:
看了网络上面的题解,有三个条件要判断第一点:
如果触发的传感器的数量少于传感器的总数量,那么一定没有遍历完所有城市。(即L == K)
第二点:
整个图必须是连通的,要不然总会有一个点无法访问。(这个可以用并查集判断)
第三点:
对于没有放传感器 或者 传感器已经触发的城市,我们的访问次数的无限制的。所以,我们这些城市的访问顺序是没有先后的,可以按照任意的顺序访问任意多次。
现在问题的关键就是:能不能按照触发顺序访问完放置传感器的城市。
我们可以有以下的思路:
设定一个 已经走过城市的集合
对于每个放置传感器的城市,我们可以通过搜索得到从当前传感器出发,不触发任何传感器且能到达的城市。
同时,这些城市中如果有一个和前面已经走过的城市的集合相连的路,那就可以得到一条路,按照传感器的触发顺序,到达前一个城市。
之后将该城市加入到已经走过的城市的集合,即可以无限次访问的该集合内的任意城市。如果找不到,那就说明无法到达前一个城市。
AC代码
[code]#include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <queue> using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const int N = 1e5 + 10; set<int> st; int n, m, K, L; //节点数,边数,传感器数,顺序 bool vis , sensor ; vector<int> g ; int pa ; //并查集,判断联通 int order ; //访问顺序 void init() { memset(vis, 0, sizeof(vis)); memset(sensor, 0, sizeof(sensor)); st.clear(); for(int i = 0; i < N; i++) { g[i].clear(); pa[i] = i; } } void add(int from, int to) { g[from].push_back(to); } int find(int x) { return (x == pa[x]) ? x : pa[x] = find(pa[x]); } void Union(int a, int b) { int r1 = find(a), r2 = find(b); if(r1 == r2) return; if(r1 < r2) pa[r2] = r1; else pa[r1] = r2; } bool bfs(int star) { queue<int> que; st.insert(star); for(int i = 1; i <= L; i++) { if(st.count(order[i])) { que.push(order[i]); vis[order[i]] = true; while(!que.empty()) { int u = que.front(); que.pop(); for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(vis[v]) continue; vis[v] = true; if(sensor[v]) st.insert(v); else que.push(v); } } }else return false; } return true; } bool judge() { int u, v; bool ok = true; while(m--) { scanf("%d%d", &u, &v); add(u, v); add(v, u); Union(u, v); } //利用并查集判断所有的点是否联通 for(int i = 2; i <= n; i++) if(find(pa[1]) != find(pa[i])) { ok = false; break; } scanf("%d", &L); if(L != K) ok = false; //输入访问顺序 for(int i = 1; i <= L; i++) scanf("%d", &order[i]); //如果bfs失败 if(!bfs(order[1])) ok = false; return ok; } int main() { int T, x; scanf("%d", &T); while(T--) { init(); scanf("%d%d%d", &n, &m, &K); //标记传感器 for(int i = 0; i < K; i++) { scanf("%d", &x); sensor[x] = true; } printf("%s\n", judge() ? "Yes" : "No"); } return 0; }
相关文章推荐
- zoj 3811 Untrusted Patrol(BFS+并查集)
- ZOJ 3811 Untrusted Patrol 并查集
- zoj 3811 Untrusted Patrol 图论 The 2014 ACM-ICPC Asia Mudanjiang Regional First Round
- ZOJ 3811 Untrusted Patrol 标记+dfs
- ZOJ 3811 Untrusted Patrol
- zoj 3811 Untrusted Patrol (按照顺序访问点+并查集||宽搜)
- ZOJ_3811_Untrusted Patrol(并查集)
- ZOJ-3811 Untrusted Patrol DFS 2014牡丹江网络赛C题
- zoj 3811 Untrusted Patrol 2014牡丹江网络赛 dfs
- ZOJ 3811 Untrusted Patrol 并查集
- ZOJ Problem Set - 3811 Untrusted Patrol
- zoj 3811 Untrusted Patrol 牡丹江网络赛c题
- Zoj 3811 Untrusted Patrol 求连通顺序
- ZOJ 3811 Untrusted Patrol 并查集+邻接表,注意所有点都要走过
- ZOJ 3811 Untrusted Patrol(BFS)
- ZOJ 3811 Untrusted Patrol【并查集】
- ZOJ 3811 Untrusted Patrol dfs
- ZOJ 3811 Untrusted Patrol 并查集 染色 BFS
- ZOJ 3811 —— Untrusted Patrol(2014牡丹江网络赛C题)
- ZOJ-3811-Untrusted Patrol 解题报告