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;
}

未完待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章