preparation for 四川大学网络安全少年班

很久没有碰竞赛了,手生……

为学习焦头烂额,抽不出时间,还是学习方法真的有问题?都高二下期了,该怎么办才好

好吧好吧,给自己打鸡血,加油加油加油啊!!!!

热血模板复习之旅开启,叮~

借用某dalao的图    高深的东西就不整了

链式前向星:

用来存图、遍历图之类的

倍增求最近公共祖先:

需要一个father数组、deep深度数组

一个dfs函数处理deep深度数组、father数组,一个find_lca函数来找祖先

// 10130
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define M 200006
#define N 100005
#define LL long long

using namespace std;

inline int wread (){
	char c(getchar ());int wans (0),flag(1);
	while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
	while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar ();}
	return wans*=flag;
}

int n;
int K,hed[N];
struct node {int v,nxt;}e[M];//e[i]表示边序号为i的边的信息 
void ad (int u,int v){//hed[u]以u节点为起点的上一条边的边序号 
	e[++K].v=v;e[K].nxt=hed[u];hed[u]=K;
}//有的只需要存终点信息即可 
//最后的遍历顺序与输入相反

int p[N][23],dep[N];

void dfs (int x,int fa){
	p[x][0]=fa;
	for (int i(1);i<=20;++i) p[x][i]=p[p[x][i-1]][i-1];
	for (int i(hed[x]);i;i=e[i].nxt){
		int v(e[i].v);
		if (v==fa)	continue;
		dep[v]=dep[x]+1;
		dfs (v,x);
	}
}

inline int fnd_lca (int a,int b){
	
	if (dep[a]>dep[b])	swap (a,b);
	for (int i(20);i>=0;--i)
		if (dep[p[b][i]]>=dep[a]) b=p[b][i];
	if (a==b)	return a;
	for (int i(20);i>=0;--i){
		if (p[a][i] == p[b][i])	continue;
		a=p[a][i];b=p[b][i];
	}
	return p[a][0];
}

int main (){
//	freopen (")
	n=wread();
	for (int i(1);i<n;++i){
		int x(wread()),y(wread());
		ad (x,y);ad(y,x);
	}
	dfs (1,1);//写-1不可以! 
//	for (int i(1);i<=n;++i){
//		printf("%d ",dep[i]);
//	}puts ("");
//	for (int i(1);i<=n;++i){
//		printf("%d ",p[i][0]);
//	}puts ("");
	int Q(wread());
	while (Q--){
		int x(wread()),y(wread());
		int ans_lca(fnd_lca(x,y));
//		printf("%d \n",ans_lca);
		printf("%lld\n",(LL)dep[x]+(LL)dep[y]-(LL)(dep[ans_lca]<<1));
	}
	return 0;
}

未完待续。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值