LCA Codeforces 100685G Gadget Hackwrench

题目传送门

题意:一棵有向的树,问u到v是否可达

分析:假设是无向树,DFS时正向的权值+1,反向的权值-1,然后找到LCA后判断dep数组和d数组就可以了

/************************************************
* Author        :Running_Time
* Created Time  :2015/10/5 星期一 10:28:49
* File Name     :G_2.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int D = 20;
const int MOD = 1e9 + 7;
const double EPS = 1e-8;
struct Edge {
    int v, d, nex;
}edge[N<<1];
int rt[D][N];
int dep[N], d[N];
int head[N], e;

void init(void) {
    memset (head, -1, sizeof (head));
    e = 0;
}

void add_edge(int u, int v, int dir) {
    edge[e] = (Edge) {v, dir, head[u]};
    head[u] = e++;
}

void DFS(int u, int fa, int dis)  {
    dep[u] = dep[fa] + 1;
    d[u] = dis;
    for (int i=head[u]; ~i; i=edge[i].nex)  {
        int v = edge[i].v;
        if (v == fa)    continue;
        rt[0][v] = u;
        DFS (v, u, dis + edge[i].d);
    }
}

int LCA(int u, int v)  {
    if (dep[u] < dep[v])    {
        swap (u, v);
    }
    for (int i=0; i<D; ++i)  {
        if ((dep[u] - dep[v]) >> i & 1)    {
            u = rt[i][u];
        }
    }
    if (u == v) return u;
    for (int i=D-1; i>=0; --i)  {
        if (rt[i][u] != rt[i][v])   {
            u = rt[i][u];
            v = rt[i][v];
        }
    }
    return rt[0][v];
}

int main(void)    {
    int n;
    while (scanf ("%d", &n) == 1)   {
        init ();
        for (int u, v, i=1; i<n; ++i) {
            scanf ("%d%d", &u, &v);
            add_edge (u, v, 1);
            add_edge (v, u, -1);
        }
        DFS (1, 0, 0);
        for (int i=1; i<D; ++i) {
            for (int j=1; j<=n; ++j)    {
                rt[i][j] = rt[i-1][rt[i-1][j]];
            }
        }
        int m;  scanf ("%d", &m);
        while (m--) {
            int u, v;   scanf ("%d%d", &u, &v);
            int f = LCA (u, v);
            if (dep[u] - dep[f] != d[f] - d[u]) puts ("No");
            else if (dep[v] - dep[f] != d[v] - d[f])    puts ("No");
            else    puts ("Yes");
        }
    }

    return 0;
}

  

时间: 2024-08-01 20:46:24

LCA Codeforces 100685G Gadget Hackwrench的相关文章

Gym100685G Gadget Hackwrench(倍增LCA)

题目大概说一棵边有方向的树,q个询问,每次询问结点u是否能走到v. 倍增LCA搞即可: 除了par[k][u]表示u结点往上走2k步到达的结点, 再加上upp[k][u]表示u结点往上走2k步经过边的状态:-1表示边都是向下,1表示都是向上,0混合. 这样u.v都往LCA上走就能知道u是否能走到v了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5

codeforces 519E A and B and Lecture Rooms LCA倍增

Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 519E Description A and B are preparing themselves for programming contests. The University where A and B study is a set of rooms connected

Codeforces Round #362 (Div. 2) C. Lorenzo Von Matterhorn LCA(最近公共祖先)

C. Lorenzo Von Matterhorn time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Barney lives in NYC. NYC has infinite number of intersections numbered with positive integers starting from 1. Ther

【CodeForces】E. Xenia and Tree(分块 + LCA)

对于两个操作,对于操作1,每次储存要修改的点,直到存了sqrt(m)个点的时候进行更新,并将图重建一次(重新记录每个点到最近染色点的距离) 对于操作2,利用LCA求现在存着的点(也就是还没有更新到图上的点)和这个点的距离的最小值以及这个点在当前图中和最近的染色的那个点的距离. 话说LCA真是个好东西=  =!这几天补一补去 题解在这里:http://codeforces.com/blog/entry/8800 #include<cmath> #include<queue> #inc

Codeforces Round #362 (Div. 2) C. Lorenzo Von Matterhorn (类似LCA)

题目链接:http://codeforces.com/problemset/problem/697/D 给你一个有规则的二叉树,大概有1e18个点. 有两种操作:1操作是将u到v上的路径加上w,2操作是求u到v上的路径和. 我们可以看出任意一个点到1节点的边个数不会超过64(差不多就是log2(1e18)),所以可以找最近相同祖节点的方式写. 用一条边的一个唯一的端点作为边的编号(比如1到2,那2就为这条边的编号),由于数很大,所以用map来存. 进行1操作的时候就是暴力加w至u到LCA(u,v

Codeforces 1000G Two-Paths 树形动态规划 LCA

原文链接https://www.cnblogs.com/zhouzhendong/p/9246484.html 题目传送门 - Codeforces 1000G Two-Paths 题意 给定一棵有 $n(2\leq n\leq 3\times 10^5)$ 个节点的树,其中节点 $i$ 有权值 $a_i$,边 $e$ 有权值 $w_e$.$(1\leq a_i,w_e\leq 10^9)$ 现在给出 $q(1\leq q\leq 4\times 10^5)$ 组询问,每组询问给定两个数 $x,

Codeforces Round #629 (Div. 3) E. Tree Queries(lca题)

https://codeforces.com/contest/1328/problem/E E. Tree Queries You are given a rooted tree consisting of nn vertices numbered from 11 to nn. The root of the tree is a vertex number 11. A tree is a connected undirected graph with n−1n−1 edges. You are

Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)

https://codeforces.com/contest/1328/problem/E 题目所描述的是一棵树,题中已明示1为root结点. 题目可以转化为,是否存在一条路径,满足集合中的k个点到路径的距离小于等于1? 思路: 1.首先倍增离线预处理出结点深度,便于后续在线询问LCA 2.对于每次的询问,依次扫描k个点.对于集合中的u和v两点,每次我们求出u和v的LCA,计算u和v到LCA的距离,如果u和v到LCA的距离同时大于1,那么说明无法找到一条路径,使得u和v到该路径链的距离小于等于1

Codeforces 519E A and B and Lecture Rooms LCA

题目链接:点击打开链接 题意: 给定n个点的树. 下面n-1行给出树 Q个询问. 每次询问 (u,v)问树上有多少个点到u点距离=到v点距离 思路: 首先这两个点的距离必须是偶数,若为奇数答案就是0 然后用lca找到中间节点即可. trick : u==v ans = n #include"cstdio" #include"iostream" #include"queue" #include"algorithm" #inclu