hdu 4674 (缩点 + 倍增LCA)
2013-08-15 09:07
309 查看
题目链接
当时看到这道题目有点想法后来看到59交0AC, 就知道肯定有不少trick,赛后看了题解才知道原来有这么多种情况。。。
其实所有的情况大致可以这么划分, u 和 v是否相同, u, v不同时, 设u所在环是cu, v所在环是cv, p所在环是cp, 根据
cu == cv再划分出两种cu != cv时再根据cu == cp || cp == cv再划分出两种情况, 基本就是这样, 对于最后几种情况
还有考虑出环的点和入环的点这个可以在dfs的过程中得到, 代码很长很丑。。。。
当时看到这道题目有点想法后来看到59交0AC, 就知道肯定有不少trick,赛后看了题解才知道原来有这么多种情况。。。
其实所有的情况大致可以这么划分, u 和 v是否相同, u, v不同时, 设u所在环是cu, v所在环是cv, p所在环是cp, 根据
cu == cv再划分出两种cu != cv时再根据cu == cp || cp == cv再划分出两种情况, 基本就是这样, 对于最后几种情况
还有考虑出环的点和入环的点这个可以在dfs的过程中得到, 代码很长很丑。。。。
#include <iostream> #include <queue> #include <cstdio> #include <cstring> #include <string> #include <cstdlib> #include <ctime> #include <algorithm> using namespace std; inline int readint() { char c = getchar(); while (!isdigit(c)) c = getchar(); int x = 0; while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x; } const int N = 100005; const int M = N << 2; const int lim = 17; // 2 ^ lim > N int in , out ; struct Tree { struct Edge { int v, ou, ov; Edge* next; void init(int a, Edge* e, int b, int c) { v = a, ou = b, ov = c; next = e; } }; Edge E[M]; Edge* it, * head ; int pa [lim], dep , dis ; bool vis ; int n; void init(int n) { this->n = n; for (int i = 0; i < n; i++) { head[i] = 0, vis[i] = 0; } it = E; } void add(int u, int v, int ou, int ov) { it->init(v, head[u], ou, ov); head[u] = it++; it->init(u, head[v], ov, ou); head[v] = it++; } int lca(int u, int v) { if (dep[u] > dep[v]) swap(u, v); if (dep[u] < dep[v]) { int d = dep[v] - dep[u]; for (int i = 0; i < lim; i++) if (d & (1 << i)) v = pa[v][i]; } if (u != v) { for (int i = lim - 1; i >= 0; i--) if (pa[u][i] != pa[v][i]) { u = pa[u][i]; v = pa[v][i]; } u = pa[u][0]; } return u; } void dfs(int u, int fa) { pa[u][0] = fa; dep[u] = dep[fa] + 1; vis[u] = 1; for (int i = 1; (1 << i) < n; i++) pa[u][i] = pa[pa[u][i - 1]][i - 1]; for (Edge* e = head[u]; e; e = e->next) { int v = e->v; if (!vis[v] && v != fa) { out[v] = e->ov, in[v] = e->ou; dfs(v, u); } } } int anc(int u, int d) { if (d < 0) return -1; if (d == 0) return u; int fa = u; for (int i = 0; (1 << i) < n; i++) { if (d & (1 << i)) { fa = pa[u][i]; u = fa; } } return fa; } void run(int rt) { dep[rt] = -1; dfs(rt, rt); } }T; struct Graph { struct Edge { int v; bool iscut; Edge* next, * pair; void init(int a, Edge* e1, Edge* e2) { this->v = a, next = e1; pair = e2; iscut = 0; } }; Edge E[M], * head ; int pre , low , no ; Edge* it; int n, id, tdfn; void init(int n) { this->n = n; for (int i = 0; i < n; i++) { head[i] = 0; pre[i] = 0; } it = E; tdfn = 1; } void add(int u, int v) { it->init(v, head[u], it + 1); head[u] = it++; it->init(u, head[v], it - 1); head[v] = it++; } int dfs(int u, int fa) { int lowu = pre[u] = tdfn++; for (Edge* e = head[u]; e; e = e->next) { int v = e->v; if (!pre[v]) { int lowv = dfs(v, u); lowu = min(lowv, lowu); if (lowv > pre[u]) { e->iscut = 1; e->pair->iscut = 1; } } else if(v != fa && pre[v] < pre[u]) { lowu = min(lowu, pre[v]); } } low[u] = lowu; return lowu; } void dfs(int u) { no[u] = id; for (Edge* e = head[u]; e; e = e->next) { if (e->iscut) continue; int v = e->v; if (no[v] == -1) dfs(v); } } void run() { dfs(0, -1); id = 0; for (int i = 0; i < n; i++) no[i] = -1; for (int i = 0; i < n; i++) if (no[i] == -1) { dfs(i); id++; } T.init(id); for (int u = 0; u < n; u++) for (Edge* e = head[u]; e; e = e->next) { int v = e->v; if (no[u] != no[v]) T.add(no[u], no[v], u, v); } T.run(0); } bool gao(int u, int v, int p) { if (u == v) { if (p == u) return 1; else return 0; } else { int tu = no[u], tv = no[v]; int tp = no[p]; if (tu == tv) { if (tp != tu) return 0; else return 1; } else { int fa = T.lca(tu, tv); if (tu == tp || tp == tv) { if (tu == tp) { if (fa != tu) { if (p != u && out[tu] == u) return 0; else return 1; } else { int d = T.dep[tv] - T.dep[tu]; int su = T.anc(tv, d - 1); if (p != u && in[su] == u) return 0; else return 1; } } else { if (fa != tv) { if (p != v && out[tv] == v) return 0; else return 1; } else { int d = T.dep[tu] - T.dep[tv]; int fu = T.anc(tu, d - 1); if (p != v && in[fu] == v) return 0; else return 1; } } } else { int du = T.dep[tu] - T.dep[tp], dv = T.dep[tv] - T.dep[tp]; int t1 = T.anc(tu, du - 1), t2 = T.anc(tv, dv - 1); if ((T.dep[tp] >= T.dep[fa]) && ((du > 0 && T.pa[t1][0] == tp) || (dv > 0 && T.pa[t2][0] == tp))) { if (tp == fa) { if (in[t1] == in[t2] && in[t1] != p) return 0; else return 1; } else { if (T.pa[t1][0] == tp) { if (out[tp] == in[t1] && out[tp] != p) return 0; else return 1; } else { if (out[tp] == in[t2] && out[tp] != p) return 0; else return 1; } } } else { return 0; } } } } } }G; int main() { int n, m, q, u, v, p; while (~scanf("%d", &n)) { m = readint(); G.init(n); for (int i = 0; i < m; i++) { u = readint(), v = readint(); u--, v--; G.add(u, v); } G.run(); q = readint(); for (int i = 0; i < q; i++) { u = readint(), v = readint(), p = readint(); u--, v--, p--; if (G.gao(u, v, p)) puts("Yes"); else puts("No"); } } return 0; }
相关文章推荐
- hdu 4674 Trip Advisor(缩点+倍增lca)
- hdu 4674 边双连通缩点+倍增lca+麻烦的讨论 (2013多校联合)
- hdu 3686 点双连通 按<割点>缩点 + 倍增lca
- HDU 5296 Annoying Problem 树链剖分 LCA 倍增法
- HDU 4757 Tree (倍增算法求LCA + 可持久化Trie树)
- hdu 5296 lca+dfs应用,lca倍增法模板
- Hdu 5458 Stability (LCA + 并查集 + 树状数组 + 缩点)
- HDU 6110 路径交(线段树+在线倍增LCA)
- HDU 6115 Factory(在线倍增LCA)
- 多校第一场 1009 hdu 5296 Annoying problem(dfs序+在线倍增lca)
- 【HDU - 2874】Connections between cities 【并查集+ 倍增法求LCA】
- hdu 2586 How far away ?(倍增法LCA)
- HDU-2586-How far away ?(倍增求LCA模板)
- HDU 2586 倍增法求lca
- HDU 5266 pog loves szh III(在线倍增LCA+ST)
- HDU 3686 Traffic Real Time Query System(点双连通缩点 + LCA)
- HDU 6065 RXD, tree and sequence(在线倍增LCA+CDQ分治+离线tarjan-LCA+dp)
- hdu 3078 Network(lca 倍增)
- HDU - 2586 How far away (lca 倍增)
- HDU - 5452 Minimum Cut 倍增lca + 思维