Gym 100685G Gadget Hackwrench(LCA)

原创 2016年08月31日 16:08:15
题目地址:http://codeforces.com/gym/100685/problem/G

思路:不考虑方向,则该图构成一棵树。对于每条有向边:对于正向边,权值为1;对于反向边,权值为-1。则对于一组查询(x,y),若有向图中Lca(x,y)到x距离为负且等于树中Lca(x,y)到x的距离,有向图中Lca(x,y)到y距离为正且等于树中Lca(x,y)到y的距离,则x,y连通。

#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debu
using namespace std;
const int maxn=1e5+50;
struct Node
{
    int p,id;
    Node(int p=0,int id=0):p(p),id(id) {}
};
int n;
queue<int> q;
int vis[maxn];
int dist[maxn];
int anc[maxn][20];
int v[maxn],d[maxn];
vector<Node> g[maxn];
void lca_dfs(int x,int dep)
{
    v[x]=1,d[x]=dep;
    for(int i=0; i<g[x].size(); i++)
    {
        int nt=g[x][i].p;
        if(!v[nt])
        {
            dist[nt]=dist[x]+g[x][i].id;
            anc[nt][0]=x;
            int k=0;
            while(anc[anc[nt][k]][k]!=0)
            {
                anc[nt][k+1]=anc[anc[nt][k]][k];
                k++;
            }
            lca_dfs(nt,dep+1);
        }
    }
}
int Lca(int x,int y)
{
    if(d[x]<d[y]) swap(x,y);
    int l=d[x]-d[y];
    int k=0;
    while(l!=0)
    {
        if(l&1) x=anc[x][k];
        l>>=1;
        k++;
    }
    k=0;
    while(x!=y)
    {
        if((anc[x][k]!=anc[y][k])||(!k))
        {
            x=anc[x][k];
            y=anc[y][k];
            k++;
        }
        else k--;
    }
    return x;
}
void init()
{
    memset(d,0,sizeof(d));
    memset(vis,0,sizeof(vis));
    memset(anc,0,sizeof(anc));
    memset(dist,0,sizeof(dist));
    for(int i=1; i<=n; i++) g[i].clear();
}
void build()
{
    memset(v,0,sizeof(v));
    for(int i=1;i<=n;i++)
        if(!v[i]) lca_dfs(i,0);
}
void query()
{
    int q;
    scanf("%d",&q);
    while(q--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        int lca=Lca(x,y);
        int tmpx=d[x]-d[lca];
        int tmpy=d[y]-d[lca];
        int distx=dist[x]-dist[lca];
        int disty=dist[y]-dist[lca];
        if(tmpx==-distx&&tmpy==disty) printf("Yes\n");
        else printf("No\n");
    }
}
int main()
{
#ifdef debug
    freopen("in.in","r",stdin);
#endif // debug
    scanf("%d",&n);
    init();
    for(int i=1; i<=n-1; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        g[x].push_back(Node(y,1));
        g[y].push_back(Node(x,-1));
        vis[y]=1;
    }
    build();
    query();
    return 0;
}


Gym 100685 G Gadget Hackwrench LCA+DFS标记

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

Gym 100685G

好坑啊。。。。查询竟然有从自身到自身。。。还是年轻啊。。 题意大致是给你一个有向图,然后给你一些查询,问你是否能从x点到y点,题意保证这个图的基图是一个树。 思路:首先因为将任何点作为根都可以,为...

Gym 100685 F Flood

F. Flood time limit per test 1 second memory limit per test 256 megabytes input st...

Gym 100685 J Just Another Disney Problem 趣题,稳定排序

J. Just Another Disney Problem time limit per test 1.5 seconds memory limit per test 256...

Codeforces gym 100685 E

Description standard input/output Statements Aladdin had found a new shiny lamp and has start...

Gym 100685 A Ariel 位统计

A. Ariel time limit per test 2 seconds memory limit per test 256 megabytes input s...

GYM 100685 J【交互题】

俄罗斯的人经常出一些交互题,比如强制离线之类的题目 这题是二分+交互 对于每一盏灯ii,我们假设前面的灯位置都排好了位置,那么就二分那些这一盏灯所在的位置,询问的次数是nlog(n)nlog(n)...

Codeforces Gym-101161E【LCA+主席树】

思路: 在这棵树上,对于每个节点u存一下从根节点(默认为1) 到 u 路径上所有线段出现的次数,那么用主席树维护所有历史信息,然后计算任意两个特定节点u, v的所有线段次数:num[线段树(u)] ...

[codeforces] Gym - 100814C Connecting Graph (并查集+LCA)

[codeforces] Gym - 100814C Connecting Graph (并查集+LCA)题目大意: 给定n个点, m个操作, 操作由两种形式 1uv1 u v 将u,vu, v...
  • ZZZZone
  • ZZZZone
  • 2017年08月09日 13:38
  • 106

Codeforces Gym 101173 H. Hangar Hurdles (LCA + 并查集)

题意在 . 和 # 所组合成的矩形 N×NN\times N 地图。kijk_{ij} 表示以 (i, j) 为中心的最大正方形(正方形范围内全是 . )的边长为 k 。问对于每个询问从 (sx, s...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Gym 100685G Gadget Hackwrench(LCA)
举报原因:
原因补充:

(最多只允许输入30个字)