题意:
一幅图某些点有监视器 监视器只记录第一次路过的时间 问 给出路线序列 是否存在满足序列的情况下遍历整幅图的点
思路:
不要想割点 割点无法处理在一个双连通分量内的多个监视器 这题就是贪心+搜索
贪心就是尽量多的使用不违背序列的点 那么我们先把序列里的第一个点和不存在监视器的点加入图 并将他们连边 对于其他的序列中的点 如果这个点存在与第一个点所形成的连通块连接的边 那么就加入这个点 否则没有答案
这里的加入点其实就是一个染色的过程 所以用搜索来搞一下
代码:
#include<cstdio> #include<iostream> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<map> #include<set> #include<vector> using namespace std; typedef long long LL; #define N 100010 #define M 400010 #define inf 2147483647 int n, m, Q, q, tot, ans; int order[N], have[N], vis[N], head[N]; struct edge { int u, v, next; bool flag; } ed[M]; void init() { tot = 0; ans = 1; memset(have, 0, sizeof(have)); memset(vis, 0, sizeof(vis)); memset(head, -1, sizeof(head)); } void add(int u, int v) { ed[tot].u = u; ed[tot].v = v; ed[tot].flag = false; ed[tot].next = head[u]; head[u] = tot++; } void dfs(int u) { vis[u] = 1; for (int i = head[u]; ~i; i = ed[i].next) { int v = ed[i].v; if (!vis[v] && !have[v]) dfs(v); } } int main() { int cas, i, u, v; scanf("%d", &cas); while (cas--) { init(); scanf("%d%d%d", &n, &m, &Q); for (i = 1; i <= Q; i++) { scanf("%d", &u); have[u] = 1; } for (i = 1; i <= m; i++) { scanf("%d%d", &u, &v); add(u, v); add(v, u); } scanf("%d", &q); for (i = 1; i <= q; i++) scanf("%d", &order[i]); if (Q != q) ans = 0; dfs(order[1]); for (i = 2; i <= q; i++) { v = 0; for (u = head[order[i]]; ~u; u = ed[u].next) { if (vis[ed[u].v]) { v = 1; break; } } if (!v) { ans = 0; break; } dfs(order[i]); } for (i = 1; i <= n; i++) { if (!vis[i]) { ans = 0; break; } } if (ans) printf("Yes\n"); else printf("No\n"); } return 0; }
时间: 2024-10-17 21:16:00