【bzoj1787】[Ahoi2008]Meet 紧急集合

求三个结点到一个结点距离之和最小的结点以及距离和

求出两两lca,其中有两个相同,答案则为另一个

感觉就是一大暴力。。。

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<queue>
  8 using namespace std;
  9
 10 #define N 500010
 11
 12 struct edge
 13 {
 14     int to,next;
 15 }e[N<<2];
 16 int head[N<<2];
 17 int cnt;
 18
 19 int fa[N][20],dep[N];
 20
 21 bool vis[N];
 22
 23 int n,q;
 24 int u,v,w;
 25 int p1,p2,p3;
 26 int t;
 27 int ans;
 28
 29 void link(int x,int y)
 30 {
 31     e[++cnt]=(edge){x,head[y]};
 32     head[y]=cnt;
 33 }
 34
 35 void dfs(int x)
 36 {
 37     vis[x]=1;
 38     for (int i=1;i<=18;i++)
 39     {
 40         if (dep[x]<(1<<i))
 41             break;
 42         fa[x][i]=fa[fa[x][i-1]][i-1];
 43     }
 44     for (int i=head[x];i;i=e[i].next)
 45     {
 46         int t=e[i].to;
 47         if (vis[t])
 48             continue;
 49         dep[t]=dep[x]+1;
 50         fa[t][0]=x;
 51         dfs(t);
 52     }
 53 }
 54
 55 int lca(int x,int y)
 56 {
 57     if (dep[x]<dep[y])
 58         swap(x,y);
 59     int t=dep[x]-dep[y];
 60     for (int i=18;i>=0;i--)
 61         if (t & (1<<i))
 62             x=fa[x][i];
 63     if (x==y)
 64         return x;
 65     for (int i=18;i>=0;i--)
 66         if (fa[x][i]!=fa[y][i])
 67             x=fa[x][i],y=fa[y][i];
 68     return fa[x][0];
 69 }
 70
 71 int dis(int x,int y)
 72 {
 73     int k=lca(x,y);
 74     return dep[x]+dep[y]-(dep[k]<<1);
 75 }
 76
 77 int main()
 78 {
 79     scanf("%d%d",&n,&q);
 80     for (int i=1;i<n;i++)
 81     {
 82         scanf("%d%d",&u,&v);
 83         link(u,v);
 84         link(v,u);
 85     }
 86     dfs(1);
 87     while (q--)
 88     {
 89         scanf("%d%d%d",&u,&v,&w);
 90         p1=lca(u,v);
 91         p2=lca(u,w);
 92         p3=lca(v,w);
 93         if (p1==p2)
 94             t=p3;
 95         else if (p1==p3)
 96             t=p2;
 97         else
 98             t=p1;
 99         ans=dis(u,t)+dis(v,t)+dis(w,t);
100         printf("%d %d\n",t,ans);
101     }
102     return 0;
103 }
时间: 2024-10-06 01:54:10

【bzoj1787】[Ahoi2008]Meet 紧急集合的相关文章

BZOJ1787 [Ahoi2008]Meet 紧急集合

水题 求出三个人每两个间的LCA,然后最小花费就是两两点之间的路径长度之和除以2 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 500005; 6 struct edge{ 7 int v,next; 8 }e[maxn*2]; 9 struct ask{ 10 int v,next,lca,d,u; 11

[bzoj1787][Ahoi2008]Meet 紧急集合(lca)

传送门 可以看出,三个点两两之间的lca会有一对相同,而另一个lca就是聚集点. 然后搞搞就可以求出距离了. ——代码 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define MAXN 1000001 5 6 using namespace std; 7 8 int n, m, cnt, ans; 9 int head[MAXN], to[MAXN], next[MAXN], de

【块状树】【LCA】bzoj1787 [Ahoi2008]Meet 紧急集合

分块LCA什么的,意外地快呢…… 就是对询问的3个点两两求LCA,若其中两组LCA相等,则答案为第三者. 然后用深度减一减什么的就求出距离了. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 using namespace std; 5 #define maxn 500001 6 struct Graph 7 {int v[maxn<<1],first[maxn<<1],n

bzoj 1787: [Ahoi2008]Meet 紧急集合

1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3016  Solved: 1344[Submit][Status][Discuss] Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT Source Day1

【BZOJ-1787】Meet紧急集合 倍增LCA

1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 2259  Solved: 1023[Submit][Status][Discuss] Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT Source Day1

1787: [Ahoi2008]Meet 紧急集合

1787: [Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT 题解: n-1条边,很明显这是一棵树 那么题目就是求3个点的LCA 我们将3个点x,y,z分别求出x,y的LCA,设为a,x,z的为b,y,z的为c 则a,b,c 3个点中必有两个相等,答案就是另外一个(自

bzoj 1787 [Ahoi2008]Meet 紧急集合(1832 [AHOI2008]聚会)

1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1841  Solved: 857[Submit][Status][Discuss] Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT Source Day1

BZOJ 1787: [Ahoi2008]Meet 紧急集合( 树链剖分 )

这道题用 LCA 就可以水过去 , 但是我太弱了 QAQ 倍增写LCA总是写残...于是就写了树链剖分... 其实也不难写 , 线段树也不用用到 , 自己YY一下然后搞一搞就过了...速度还挺快的好像= = #9 ---------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algori

【Ahoi2008】【lca】【bzoj1787】Meet 紧急集合

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1787 题解: 求出三个点两两之间的lca会发现有两个是一样的,然后我们选那个不一样的就好了. #include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; struct use{ int st,en; }b[5000001]; in