• TZOJ 4651 zry和他的的灯泡们(lca)


    描述

    zry有一个收集灯泡的习惯,他把灯泡的阴极都共地,阳极连成一颗树,这样的话,他只要在任意一个灯泡的阳极加上合适的电压,所有灯泡都能亮起来。不幸的是,有一对灯泡之间的阳极连线断掉了,这样的话,这颗灯泡树就还有一部分能亮,一部分不能亮了。zry想知道如果他在任意一个灯泡的阳极上加电压,这一对灯泡的哪一个会亮?

    输入

    首先是一个正整数T(1<=T<=10)表示测试数据的组数。
    对于每一组测试数据:
    第一行是一个整数n,q(3<=n,q<=100000),n表示灯泡总数,q表示查询个数。
    接下来的n-1行,每行2个整数x,y(1<=x,y<=n),表示灯泡x和灯泡y的阳极相连。(数据保证合法,是一棵树)
    接下来的q行,每行3个整数,a,b,c(1<=a,b,c<=n,数据保证合法,灯泡a和灯泡b之间有边且a不等于b)表示灯泡a和灯泡b之间阳极连线断开的话,在c的阳极加一个电压。

    输出

    每个查询之间相互独立,对于每个查询输出a和b哪一个会亮,输出a或者b即可。

    样例输入

    1
    3 1
    1 2
    2 3
    1 2 3

    样例输出

    2

    题意

    给一棵树,每次询问断掉一条边(a,b),问c和a还是b连通。

    题解

    不妨这么想,如果删了(a,b),那么c和两个点的距离哪个近就输出哪个。

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int N=1e5+5,L=18;
     5 int dep[N],fa[N][L],lg[N],n;
     6 bool vis[N];
     7 vector<int>G[N];
     8 void dfs(int u)
     9 {
    10     vis[u]=1;
    11     for(int i=0;i<G[u].size();i++)
    12     {
    13         int v=G[u][i];
    14         if(vis[v])continue;
    15         fa[v][0]=u;
    16         dep[v]=dep[u]+1;
    17         dfs(v);
    18     }   
    19 }
    20 void RMQ()
    21 {
    22     for(int j=1;(1<<j)<=n;j++)
    23         for(int i=1;i<=n;i++)
    24             fa[i][j]=fa[fa[i][j-1]][j-1];
    25 }
    26 int lca(int x,int y)
    27 {
    28     if(dep[x]<dep[y])swap(x,y);
    29     while(dep[x]>dep[y])x=fa[x][lg[dep[x]-dep[y]]-1];
    30     if(x==y)return x;
    31     for(int k=lg[dep[x]];k>=0;k--)
    32         if(fa[x][k]!=fa[y][k])
    33             x=fa[x][k],y=fa[y][k];
    34     return fa[x][0];
    35 }
    36 int dist(int u,int v){return dep[u]+dep[v]-2*dep[lca(u, v)];}
    37 int main()
    38 {
    39     for(int i=1;i<N;i++)lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    40     int t;
    41     scanf("%d",&t);
    42     while(t--)
    43     {
    44         int q;
    45         scanf("%d%d",&n,&q);
    46         for(int i=1;i<=n;i++)vis[i]=0;
    47         for(int i=1;i<=n;i++)G[i].clear();
    48         for(int i=1,u,v;i<n;i++)
    49         {
    50             scanf("%d%d",&u,&v);
    51             G[u].push_back(v);
    52             G[v].push_back(u);
    53         }
    54         dfs(1);
    55         RMQ();
    56         while(q--)
    57         {
    58             int a,b,c;
    59             scanf("%d%d%d",&a,&b,&c);
    60             int dis1=dist(a,c),dis2=dist(b,c);
    61             if(dis1<dis2)printf("%d
    ",a);
    62             else printf("%d
    ",b);
    63         }
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    gitlab配置ssh连接
    java 函数编程之Consumer接口的使用
    一枚程序猿的MacBook M1详细体验报告
    【线上问题排查技巧】动态修改LOGGER日志级别
    【线上排查实战】AOP切面执行顺序你真的了解吗
    阿里巴巴Canal常见问题:重复解析/Filter失效/消费落后
    使用Binlog日志恢复误删的MySQL数据实战
    Git实战技巧:恢复被强制push -f失踪的代码
    一次完整的JVM堆外内存泄漏故障排查记录
    Java线上问题排查神器Arthas快速上手与原理浅谈
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/11628885.html
Copyright © 2020-2023  润新知