Gym 100685 G Gadget Hackwrench LCA+DFS标记

来源:互联网 发布:js根据name获取标签 编辑:程序博客网 时间:2024/05/17 23:49

G. Gadget Hackwrench
time limit per test
2 seconds
memory limit per test
64 megabytes
input
standard input
output
standard output

Chip 'n' Dale rescue rangers! But observant viewers know that help is usually required by Chip and Dale themselves. Today you are in the role of cunning Gadget Hackwrench.

So, Chip and Dale are again in the paws of Fat Cat. He doesn't like rodents much and therefore prepared a treacherous test. He is going to put them to a labyrinth and see if they can escape from it. The labyrinth is actually built as a tree where each edge has fixed direction (by definition tree is a connected unoriented graph without cycles).

Gadget has intercepted a talk between Fat Cat and his henchmen about future tests. For each test round she knows the exact location where Chip and Dale are to be put by Fat Cat and the location of an exit. Gadget wants to compute whether they will be able to find an exit for each test.

Input

The first line of input contains an integer N (1 ≤ N ≤ 105) — the number of vertices in a graph.

On the next N - 1 lines of input directed arcs of the tree are given. On the (i + 1)th line integer numbers ai and bi are given (1 ≤ ai, bi ≤ N) denoting an arc from vertex ai to vertex bi. It is guaranteed that arcs a1, a2, ..., an - 1 without orientation form a tree.

Then a string with integer number M (1 ≤ M ≤ 105) is given — the number of queries to process. Next M lines describe queries:(n + 1 + i)th line contain integers xi and yi (1 ≤ xi, yi ≤ N).

Output

For each query please output a separate line containing 'Yes' (without quotes) if graph contains a path between xi and yi, or 'No' (without quotes) in other case.

Sample test(s)
input
41 23 14 161 23 22 34 24 32 1
output
YesYesNoYesNoNo


题目链接:http://codeforces.com/gym/100685/problem/G

题目大意:给定一张有向无环图,n个点,问从一点A到另外一点B是否存在一条通路可达。

思路:首先,以双向边的形式构建出LCA的st表,并标记正向边(flag = 0)与反向边(flag = 1)。然后,DFS一次,记录三项内容,分别是该节点所在深度cnt[],从该点沿正向走的最远距离dir_u[]和从该点沿反向走的最远距离dir_v[],于是,对于一组查询A和B,从A到B可达,当且仅当A到lca的距离不超过A的正向最远距离,同时B到lca的距离不超过B的反向最远距离。

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <algorithm>#include <vector>#include <limits.h>#include <queue>#include <map>#include <set>using namespace std;typedef long long LL;#define pll pair<LL, LL>#define pii pair<int, int>#define X first#define Y second#define MAXN 200010#define lson l, mid, (rt << 1)#define rson mid + 1, r, (rt << 1 | 1)const double eps = 1e-10;int head[MAXN];int dp[MAXN][20], deep[MAXN];int dir_u[MAXN], dir_v[MAXN], cnt[MAXN];int totedge = 0, t, n, Q;bool vis[MAXN];struct node {    int to, next, flag;} edge[MAXN << 1];void init() {    totedge = 0;    memset(vis, false, sizeof vis);    memset(head, -1, sizeof head);    memset(dp, 0, sizeof dp);    memset(deep, 0, sizeof deep);    memset(dir_u, 0, sizeof dir_u);    memset(dir_v, 0, sizeof dir_v);    memset(cnt, 0, sizeof cnt);}void add(int from, int to, int flag) {    edge[totedge].to = to;    edge[totedge].next = head[from];    edge[totedge].flag = flag;    head[from] = totedge++;}void DFS(int u, int step) {    if(vis[u]) return ;    vis[u] = true;    if(step == 0) dp[u][0] = u;    deep[u] = step;    for(int i = 1; i < 20; i++)        dp[u][i] = dp[dp[u][i-1]][i-1];    for(int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].to;        if(vis[v]) continue;        dp[v][0] = u;        DFS(v, step + 1);    }}int LCA(int u, int v) {    if(deep[u] > deep[v]) swap(u, v);    int deep_len = deep[v] - deep[u];    int tu = u, tv = v;    for(int j = deep_len, i = 0; j ; j>>=1, i++) {        if(j & 1) tv = dp[tv][i];    }    if(tu == tv) return tu;    for(int i = 20 - 1; i >= 0; i--) {        if(dp[tu][i] == dp[tv][i]) continue;        tu = dp[tu][i], tv = dp[tv][i];    }    return dp[tu][0];}void DFS2(int u, int pre) {    for(int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].to;        if(v == pre) continue;        cnt[v] = cnt[u] + 1;        if(edge[i].flag == 0) {            dir_v[v] = dir_v[u] + 1;            dir_u[v] = 0;        } else {            dir_u[v] = dir_u[u] + 1;            dir_v[v] = 0;        }        DFS2(v, u);    }}int main() {    while(~scanf("%d", &n)) {        init();        int a, b;        for(int i = 0; i < n - 1; i++) {            scanf("%d%d", &a, &b);            add(a, b, 0);            add(b, a, 1);        }        DFS(1, 0);        scanf("%d", &Q);        DFS2(1, -1);        while(Q--) {            scanf("%d%d", &a, &b);            int lca = LCA(a, b);            int cnt1 = cnt[a] - cnt[lca];            int cnt2 = cnt[b] - cnt[lca];            if(cnt1 > dir_u[a] || cnt2 > dir_v[b]) {                puts("No");            } else puts("Yes");        }    }    return 0;}


0 0
原创粉丝点击