【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];
int cnt,u,v,point[500001],next[5000001],deep[500001],fa[500001][20],n,m,x,y,z,aa,bb,cc,vis[1000001];
void add(int x,int y)
{
	++cnt;next[cnt]=point[x];point[x]=cnt;
	b[cnt].st=x;b[cnt].en=y;
}
void dfs(int x)
{
	 vis[x]=1;
	for (int i=1;i<=15;i++)
     {
	  if ((1<<i)>deep[x]) break;
	  fa[x][i]=fa[fa[x][i-1]][i-1];
     }
	for (int i=point[x];i;i=next[i])
	{
		if (vis[b[i].en]) continue;
		  	deep[b[i].en]=deep[x]+1;
		  	fa[b[i].en][0]=x;
		  	dfs(b[i].en);
	}
}
int lca(int x,int y)
{
	int t;
	if (deep[x]<deep[y]) swap(x,y);
	t=deep[x]-deep[y];
	for (int i=0;i<=15;i++)
	  if ((1<<i)&t) x=fa[x][i];
	for (int i=15;i>=0;i--)
	  	 if (fa[x][i]!=fa[y][i])
	  	 {
	  	 	 x=fa[x][i];
	  	 	 y=fa[y][i];
	  	 }
	if (x==y) return x;
	else return fa[x][0];
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n-1;i++)
	  {
	  	 scanf("%d%d",&u,&v);
	  	 add(u,v);add(v,u);
	  }
	for (int i=0;i<=15;i++) fa[1][i]=1;
	dfs(1);
    for (int i=1;i<=m;i++)
    {
       int tt,zu;
	   scanf("%d%d%d",&x,&y,&z);
       aa=lca(x,y);bb=lca(x,z);cc=lca(y,z);
       if (aa==bb) zu=cc;if (aa==cc) zu=bb;if (bb==cc) zu=aa;
       aa=lca(zu,x);bb=lca(zu,y);cc=lca(zu,z);
       tt=-(deep[aa]-deep[zu])-(deep[aa]-deep[x])-(deep[bb]-deep[zu])-(deep[bb]-deep[y])-(deep[cc]-deep[zu])-(deep[cc]-deep[z]);
       printf("%d %d\n",zu,tt);
    }
}
时间: 2024-10-09 09:17:45

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

【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

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

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

bzoj 1787 Meet 紧急集合

Meet 紧急集合 这个题是在脖子oj(清北某奆佬给起的名字)八中oj(大视野在线评测)上的. 给出bzoj链接. 这个题还是求最近公共祖先的问题. 而该题不同于别的题,它是需要求三个点的最近公共祖先. 我们就需要求出三个点两两之间的LCA. 而这三个LCA之间,必有两个是相同的. 如果两个点相同,那另一点就是那三个点的LCA. 如果三个点都相同,那么该点就是那三个点的LCA. 最后还需要统计走过的边的长度. 三个点都相同的情况很好搞,就是计算三个点与那个LCA的深度差,加起来就是答案. 但是两

【BZOJ1787】【Ahoi2008】Meet 紧急集合 LCA、双倍经验

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43235305"); } 233-- [BZOJ1832][AHOI2008]聚会 倍增lca 就是这道题.输入输出都没有改. http://blog.csdn.net/vmurder/article/details/42607739 题解也在以前那篇

[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

【bzoj1787】[Ahoi2008]Meet 紧急集合 倍增LCA

题目描述 输入 输出 样例输入 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处,大概画一下就看出来了. 然后有x到y的距离为deep[x]+deep[y]-2*deep[lcaxy] 那么x.y.z三点到lcaxy的距离为deep[x]+deep[y]-2*deep[lcaxy]+deep[lcaxy]+deep[x]-deep[lcaxyz] 到