zoukankan      html  css  js  c++  java
  • [AHOI2008]紧急集合 / 聚会

    紧急集合 / 聚会

    题目大意:

    给出一个无向图,每一次给出图中的三个点,求离三个点距离之和最小的点。

    解决方法:

    倍增LCA。

    首先我们两两点之间求出LCA,那么离他们距离之和最近的点就是三个点中深度最深的点,想一想为什么?

    我们假设存在一个点离三个点距离之和更近且深度更浅,那么我们将它的深度往下走一个,一定会有两个点距离-1,一个点+1,所以往下移更靠近正解opt,那么我们就可以得出我们上述结论合法。

    而关于距离之和,由于dis(u,v)=dep[u]+dep[v]-dep[lca(u,v)],那么我们把三个点两两之间∑一下再除以二就能得到答案了,式子就不推了。。。

    dis=dep[x]+dep[y]+dep[z]-dep[lca(x,y)]-dis[lca(y,z)]-dis[lca(x,z)]

    最后附上本题代码:

      1 #include<cstdio>
      2 #include<iostream>
      3 #define maxn 500000
      4 using namespace std;
      5 
      6 int n,m,root,cnt;
      7 int head[maxn+5],dep[maxn+5],f[maxn+5][30];
      8 bool vis[maxn+5];
      9 struct EDGE
     10 {
     11     int nxt,to;
     12 };
     13 EDGE edge[maxn*2+5];
     14 
     15 int max(int x,int y)
     16 {
     17     if(dep[x]>=dep[y])
     18     {
     19         return x;
     20     }
     21     return y;
     22 }
     23 int abs(int x)
     24 {
     25     if(x<0)
     26     {
     27         return -x;
     28     }
     29     return x;
     30 }
     31 void add(int x,int y)
     32 {
     33     edge[++cnt].to=y;
     34     edge[cnt].nxt=head[x];
     35     head[x]=cnt;
     36 }
     37 void pre_fir(int u,int fa)
     38 {
     39     dep[u]=dep[fa]+1;
     40     for(int i=0;i<=25;i++)
     41     {
     42         f[u][i+1]=f[f[u][i]][i];
     43     }
     44     for(int i=head[u];i;i=edge[i].nxt)
     45     {
     46         if(edge[i].to==fa)
     47         {
     48             continue;
     49         }
     50         f[edge[i].to][0]=u;
     51         pre_fir(edge[i].to,u);
     52     }
     53 }
     54 int LCA(int x,int y)
     55 {
     56     if(dep[x]<dep[y])
     57     {
     58         swap(x,y);
     59     }
     60     for(int i=25;i>=0;i--)
     61     {
     62         if(dep[f[x][i]]>=dep[y])
     63         {
     64             x=f[x][i];
     65         }
     66         if(x==y)
     67         {
     68             return x;
     69         }
     70     }
     71     for(int i=25;i>=0;i--)
     72     {
     73         if(f[x][i]!=f[y][i])
     74         {
     75             x=f[x][i];
     76             y=f[y][i];
     77         }
     78     }
     79     return f[x][0];
     80 }
     81 int main()
     82 {
     83     scanf("%d%d",&n,&m);
     84     for(int i=1;i<=n-1;i++)
     85     {
     86         int x,y;
     87         scanf("%d%d",&x,&y);
     88         add(x,y);
     89         add(y,x);
     90         vis[y]=1;
     91     }
     92     for(int i=1;i<=n;i++)
     93     {
     94         if(vis[i]==0)
     95         {
     96             root=i;
     97             break;
     98         }
     99     }
    100     dep[root]=1;
    101     pre_fir(root,0);
    102     for(int i=1;i<=m;i++)
    103     {
    104         int x,y,z;
    105         scanf("%d%d%d",&x,&y,&z);
    106         int ans1=LCA(x,y),ans2=LCA(y,z),ans3=LCA(x,z);
    107         int ans=max(max(ans1,ans2),ans3);
    108         printf("%d %d
    ",ans,dep[x]+dep[y]+dep[z]-dep[ans1]-dep[ans2]-dep[ans3]);
    109     }
    110     return 0;
    111 }
  • 相关阅读:
    感受MapXtreme2004之三:
    GIS集成技术之四:Office, AutoCAD, MatLab集成
    GIS集成技术之二:三库集成
    SQL日期格式化应用大全
    .net中的windows service与服务操作
    大小写转换
    sql系统表syscolumns中 xtype 所有值对应的类型名称
    在.net中读写config文件的各种方法
    VS.NET打包安装
    C#数字格式化输出
  • 原文地址:https://www.cnblogs.com/yufenglin/p/10579901.html
Copyright © 2011-2022 走看看