P3884 [JLOI2009]二叉树问题
查看原帖
P3884 [JLOI2009]二叉树问题
313668
DoubleBean楼主2020/11/29 14:52

萌新第一次发帖询问,也不知道排版对不对....

我在最后一个测试点wa了,找了很久都没找到Bug

我先解释下我是怎么处理求u和v之间距离的:

一棵二叉树,首先看输入的两个结点是否相等,相等直接返回。

另一种情况就是u和v深度不同,就是说不在同一层,这时候就要看深度哪个大,为了保证u结点的深度始终是大于v的,所以我要对deep[u]<deep[v]的情况进行处理,就是进行swap交换

(可能你会疑惑为什么要判断两个结点的深度大小,而且还要进行swap交换,后面会解释)

前面的操作就保证了u的结点深度大于v了,就一直找u的父亲结点,直到u的深度等于v的深度,也就是说这时候u和v是在同一层了。

所以说swap操作就是因为我后面的操作只是对u进行,没有对v进行,所以要保证u是更深的那个结点。

通过前面的操作后u和v就是同一起跑线了,然后再同时一起向上找祖先结点,找到了共同的祖先就返回。

还有一种情况就是最开始时u和v结点的深度就是一样的,这时候就判断直接上一步的那个操作:就是一起找共同祖先

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 300+5;
int father[maxn], deep[maxn], width[maxn]; //父亲,深度,宽度 
int n, maxdeep=1, maxwidth = 0;

int lca(int u, int v)
{
	if(deep[u]<deep[v]) //若u的深度小于v的深度
		swap(u, v);
   //使得u和v在同一深度(层)
	while(deep[u]!=deep[v]){
		u = father[u];
	}
	if(u==v){
		return v;
	}
  	//共同找最近的祖先结点
	while(father[u]!=father[v]){
		u = father[u];
		v = father[v];
	}
	return father[u];
}
int main(){
	int u, v, i;
	cin>>n;
	deep[1] = 1;
	width[1] = 1; 
	for(i=1;i<n;i++){
		cin>>u>>v;
		father[v] = u;  //父结点就是u 
		deep[v] =deep[u] + 1; //孩子结点的深度就是父结点深度+1 
		width[deep[v]]++;  //宽度也就是同一深度(层)最多结点个数
		if(maxdeep<deep[v]){
			maxdeep = deep[v]; //更新最大深度
		}
	}

	//更新最大宽度 
	for(i=1;i<maxdeep;i++){
		if(maxwidth<width[i]){
			maxwidth = width[i];
		}
	}
	cout<<maxdeep<<endl<<maxwidth<<endl;
	
	//算结点u到结点v间距离 
	cin>>u>>v;
	cout<<(deep[u]-deep[lca(u,v)])*2+deep[v]-deep[lca(u,v)];
	return 0;
}
2020/11/29 14:52
加载中...