BZOJ——1787: [Ahoi2008]Meet 紧急集合

http://www.lydsy.com/JudgeOnline/problem.php?id=1787

题目描述

输入

输出

样例输入

6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6

样例输出

5 2
2 5
4 1
6 0

提示

易发现:三个点两两求出LCA,一定至少有两个LCA相等

    若只有两个相等,那聚集点就是剩下的LCA

    若三个相等,那聚集点就是LCA

 1 #include <algorithm>
 2 #include <cstdio>
 3 #include <vector>
 4
 5 using namespace std;
 6
 7 const int N(1e5*5+15);
 8 vector<int>vec[N];
 9 int n,m,x,y,z;
10 int anspoint,anssum;
11 int deep[N],dad[N],size[N],top[N];
12
13 void DFS(int x)
14 {
15     size[x]=1; deep[x]=deep[dad[x]]+1;
16     for(int i=0;i<vec[x].size();i++)
17         if(dad[x]!=vec[x][i])
18         {
19             dad[vec[x][i]]=x;
20             DFS(vec[x][i]);
21             size[x]+=size[vec[x][i]];
22         }
23 }
24
25 void DFS_(int x)
26 {
27     int t=0; if(!top[x]) top[x]=x;
28     for(int i=0;i<vec[x].size();i++)
29         if(vec[x][i]!=dad[x]&&size[t]<size[vec[x][i]]) t=vec[x][i];
30     if(t) top[t]=top[x],DFS_(t);
31     for(int i=0;i<vec[x].size();i++)
32         if(vec[x][i]!=dad[x]&&t!=vec[x][i]) DFS_(vec[x][i]);
33 }
34
35 int LCA(int x,int y)
36 {
37     while(top[x]!=top[y])
38     {
39         if(deep[top[x]]<deep[top[y]]) swap(x,y);
40         x=dad[top[x]];
41     }
42     if(deep[x]>deep[y]) swap(x,y);
43     return x;
44 }
45
46 int main()
47 {
48     scanf("%d%d",&n,&m);
49     for(int i=1;i<n;i++)
50     {
51         scanf("%d%d",&x,&y);
52         vec[x].push_back(y);
53         vec[y].push_back(x);
54     }
55     DFS(1); DFS_(1);
56     for(;m;m--)
57     {
58         scanf("%d%d%d",&x,&y,&z);
59         anspoint=LCA(x,y)^LCA(x,z)^LCA(y,z);
60         anssum =deep[x]+deep[anspoint]-(deep[LCA(x,anspoint)]<<1);
61         anssum+=deep[y]+deep[anspoint]-(deep[LCA(y,anspoint)]<<1);
62         anssum+=deep[z]+deep[anspoint]-(deep[LCA(z,anspoint)]<<1);
63         printf("%d %d\n",anspoint,anssum);
64     }
65     return 0;
66 }
时间: 2024-10-23 11:28:46

BZOJ——1787: [Ahoi2008]Meet 紧急集合的相关文章

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 [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

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 &amp;&amp; bzoj 1832: [Ahoi2008]Meet 紧急集合(倍增LCA)算法竞赛进阶指南

题目描述 原题连接 Y岛风景美丽宜人,气候温和,物产丰富. Y岛上有N个城市(编号\(1,2,-,N\)),有\(N-1\)条城市间的道路连接着它们. 每一条道路都连接某两个城市. 幸运的是,小可可通过这些道路可以走遍Y岛的所有城市. 神奇的是,乘车经过每条道路所需要的费用都是一样的. 小可可,小卡卡和小YY经常想聚会,每次聚会,他们都会选择一个城市,使得3个人到达这个城市的总费用最小. 由于他们计划中还会有很多次聚会,每次都选择一个地点是很烦人的事情,所以他们决定把这件事情交给你来完成. 他们

BZOJ 1787 AHOI2008 紧急集合 倍增LCA

题目大意:给定一棵树,多次询问到三个点距离之和最小的点和距离 首先易知到两个点距离之和最小的点一定在两点间的路径上 于是到三个点距离之和最小的点一定在两两之间路径的交点上 然后很容易就会知道这个交点一定是其中两个点的LCA(其实是我不会证) 此外为什么不会是三个点共同的LCA呢?因为三个点共同的LCA一定是至少一对点的LCA 证明略(其实我也不会证) 然后就是枚举两两之间的LCA 求一下距离 取最小即可 然后就是倍增LCA的问题了 我的倍增LCA怎么又挂了 还能不能写对了0.0 #include

【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 namesp

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