BZOJ 1787 緊急集合

1787: [Ahoi2008]Meet 緊急集合

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 1220  Solved: 500
[Submit][Status]

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

——分割線——

臥槽、、感覺好不好QAQ我寫的程序最近總是評測CE!這、、讓我怎麼去考NOIP!好吧,這次是因爲用了IO庫裏的一個Swap函數,可是明明在IO庫裏啊、、、爲什麼會CE、、看來我以後不能提前寫好多好多頭文件了、、、、

言歸正傳,這題就是練一下LCA,臥槽,這次我感受到了數組地址衝突導致的莫名其妙數據不正常問題,調了好久才發現是地址衝突QAQ!LCA感覺還是不是很熟練,找時間再寫一題,這道題吧,很容易得到,他們的集合點就是三個點兩兩的LCA之一,都算出來比一下距離就好啦~

代碼:

/*Author:WNJXYK*/
#include<cstdio>
using namespace std;

#define LL long long

const int Maxn=500000;
int n,m;
struct Node{
	int u;
	int nxt;
	Node(){}
	Node(int a,int b){
		u=a;
		nxt=b;
	}
};
int nume=0;
Node link[2*Maxn+10];
int links[Maxn+10];
int visited[Maxn+10];
int lca[Maxn+10][20];
int depth[Maxn+10];
int Mlca=20;

int dfs(int x,int deep){
	depth[x]=deep;
	visited[x]=true;
	for(int i=1;i<Mlca;i++){
		lca[x][i]=lca[lca[x][i-1]][i-1];
	}
	for (int i=links[x];i;i=link[i].nxt){
		int point=link[i].u;
		if (!visited[point]){
			lca[point][0]=x;
			dfs(point,deep+1);
		}
	}
}

inline void swin(int &x,int step){
	for (int i=0;step>0;i++){
		if (step%2==1) x=lca[x][i];
		step/=2;
	}
}

inline void swap(int &x,int &y){
	x=x+y;
	y=x-y;
	x=x-y;
}

inline int LCA(int x,int y){
	if (depth[x]>depth[y]) swap(x,y);
	swin(y,depth[y]-depth[x]);
	if (x==y) return x;
	for (int i=0;;){
		for(i=0;lca[x][i]!=lca[y][i];i++);
		if (i==0) return lca[x][i];
		x=lca[x][i-1];
		y=lca[y][i-1];
	}
	return -1;
}

inline void addEdge(int x,int y){
	link[++nume]=Node(y,links[x]);
	links[x]=nume;
}

inline int dist(int x,int y){
	int l=LCA(x,y);
	return depth[x]+depth[y]-2*depth[l];
}

int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		addEdge(x,y);
		addEdge(y,x);
	}
	lca[1][0]=1;
	dfs(1,1);
	for (int i=1;i<=m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		int lx,ly,lz;
		lx=LCA(x,y);
		ly=LCA(y,z);
		lz=LCA(z,x);
		//cout<<lx<<" "<<ly<<" "<<lz<<" "<<endl;
		int l=lx^ly^lz;
		int ans=dist(l,x)+dist(l,y)+dist(l,z);
		printf("%d %d\n",l,ans);
	}
	return 0;
}



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