Gym 100685 G Gadget Hackwrench LCA+DFS标记
2015-10-04 20:20
337 查看
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
output
题目链接: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代码:
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
4 1 2 3 1 4 1 6 1 2 3 2 2 3 4 2 4 3 2 1
output
Yes Yes No Yes No No
题目链接: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; }
相关文章推荐
- Linux异步回调架构的实现
- Android数据存储与IO
- 如何使用Axure:[8]制作联动下拉菜单
- Http服务器实现文件上传与下载(四)
- 【转】Linux压缩&解压缩命令全览
- Centos之LAMP环境搭建
- Centos之LAMP环境搭建
- 【JS】day03_JavaScript对象_常用内置对象一
- HDU2082(母函数)
- 机器学习笔记 线性判别分析(中)
- 万能的自动化测试框架
- 黑马程序员——java基础日记——继承、接口
- 41. First Missing Positive (Map)
- JAVA实验一
- URAL 1348 Goat in the Garden 2(点到线段的距离)
- 腾讯2014年实习生招聘广州站offer经历(TEG-后台开发)
- IE按F12,开发者工具已经在最低点,那么国家就不会出错
- 关于家用路由器下挂多个设备包括下挂路由器的操作
- 一个JavaScript实现的贷款计算器
- 基础语法