• 洛谷 P4281 [AHOI2008] 紧急集合 题解


    挺好的一道题,本身不难,就把求两个点的LCA变为求三个点两两求LCA,不重合的点才是最优解。值得一提的是,最后对答案的处理运用差分的思想:假设两点 一点深度为d1,另一点

    深度为d2,它们LCA深度为d3,这二者之间的距离即为d1+d1-2*d3,只要将这两点推广成三点即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 500000
     6 using namespace std;
     7 inline int read() 
     8 {
     9     int x=0;
    10     bool f=1;
    11     char c=getchar();
    12     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
    13     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    14     if(f) return x;
    15     return 0-x;
    16 }
    17 int n,m;
    18 long long ans;
    19 int f[maxn+10][25],dep[maxn+10],t;
    20 struct node
    21 {
    22     int from,to,nex;
    23 }edge[2*maxn+10];
    24 int head[2*maxn+10],tot=0;
    25 inline void add(int x,int y)
    26 {
    27     edge[++tot].from=x;
    28     edge[tot].to=y;
    29     edge[tot].nex=head[x];
    30     head[x]=tot;
    31 }
    32 inline void Deal_first(int u,int father)
    33 {
    34     dep[u]=dep[father]+1;
    35     for(int i=0;i<=19;i++)
    36     {
    37         f[u][i+1]=f[f[u][i]][i];
    38     }
    39     for(int e=head[u];e;e=edge[e].nex)
    40     {
    41         int v=edge[e].to;
    42         if(v==father)continue;
    43         f[v][0]=u;
    44         Deal_first(v,u);
    45     }
    46 }
    47 inline int LCA(int x,int y)
    48 {
    49     if(dep[x]<dep[y])swap(x,y);
    50     for(int i=20;i>=0;i--)
    51     {
    52         if(dep[f[x][i]]>=dep[y])x=f[x][i];
    53         if(x==y)return x;
    54     }
    55     for(int i=20;i>=0;i--)
    56     {
    57         if(f[x][i]!=f[y][i])
    58         {
    59             x=f[x][i];
    60             y=f[y][i];
    61         }
    62     }
    63     return f[x][0];
    64 }
    65 int main()
    66 {
    67     n=read();m=read();
    68     for(int i=1;i<=n-1;i++)
    69     {
    70         int a,b;
    71         a=read();b=read();
    72         add(a,b);add(b,a);
    73     }
    74     Deal_first(1,0);
    75     for(int i=1;i<=m;i++)
    76     {
    77         ans=0;
    78         int a,b,c;
    79         a=read();b=read();c=read();
    80         int t1=LCA(a,b);
    81         int t2=LCA(a,c);
    82         int t3=LCA(b,c);
    83         if(t1==t2)t=t3;
    84         else if(t1==t3)t=t2;
    85         else if(t2==t3)t=t1;
    86         ans=dep[a]+dep[b]+dep[c]-dep[t1]-dep[t2]-dep[t3];
    87         printf("%d %lld
    ",t,ans);
    88     }
    89     return 0;
    90 }
    请各位大佬斧正(反正我不认识斧正是什么意思)
  • 相关阅读:
    [转+]C语言复杂声明
    c和c++数组初始化一点小区别
    [转]Linux ftp命令的使用方法
    Ubuntu 12.04 英文版中文输入法设置
    [转]Android手机中获取手机号码和运营商信息
    把google地圖放在Crm Entity中
    为什么报表里面记录的创建时间 比我们电脑客户端的世界时间 隔8个小时?这个是什么原因?
    print style Iframe
    取出MSCRM父窗口的欄位的值
    Display Fetch in IFRAME – Part 2
  • 原文地址:https://www.cnblogs.com/handsome-zyc/p/11237610.html
Copyright © 2020-2023  润新知