bzoj1787: [Ahoi2008]Meet 紧急集合

树链剖分。求任意三个点的最小集合距离。有一个结论。但是不会也可以枚举。注意如果是两棵子树中的点那么原来的计算方法就错了。WA了一次。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
#define REP(i,s,t) for(int i=s;i<=t;i++)
#define adde(u,v) add(u,v),add(v,u)
#define op() pt=edges;clr(head,0);
#define qwq(x) for(edge *o=head[x];o;o=o->next)
int read(){
	int x=0;char c=getchar();bool f=true;
	while(!isdigit(c)) {
		if(c=='-') f=false;c=getchar();
	}
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return f?x:-x;
}
const int nmax=500005;
const int inf=0x7f7f7f7f;
struct edge{
	int to;edge *next;
};
struct data{
	int p,c;
	data(int p,int c):p(p),c(c){}
};
edge edges[nmax<<1],*pt,*head[nmax];
int size[nmax],son[nmax],fa[nmax],dep[nmax],idx[nmax],id[nmax<<2],tp[nmax];
void add(int u,int v){
	pt->to=v;pt->next=head[u];head[u]=pt++;
}
void dfs(int x){
	size[x]=1;
	qwq(x){
		int to=o->to;
		if(to==fa[x]) continue;
		dep[to]=dep[x]+1;fa[to]=x;
		dfs(to);size[x]+=size[to];
		if(!son[x]||size[to]>size[son[x]]) son[x]=to;
	}
}
void DFS(int x,int top){
	id[++id[0]]=x;idx[x]=id[0];tp[x]=top;
	if(son[x]) DFS(son[x],top);
	qwq(x) if(!idx[o->to]) DFS(o->to,o->to);
}
int query(int a,int b){
	while(tp[a]!=tp[b]){
		if(dep[tp[a]]>dep[tp[b]]) swap(a,b);
		b=fa[tp[b]];
	}
	if(idx[a]<idx[b]) return a;
	return b;
}
int getdist(int a,int b){
	int ans=0;
	while(tp[a]!=tp[b]){
		if(dep[tp[a]]>dep[tp[b]]) swap(a,b);
		ans+=idx[b]-idx[tp[b]]+1;
		b=fa[tp[b]];
	}
	if(dep[a]>dep[b]) swap(a,b);
	return ans+=idx[b]-idx[a];
}
data qsum(int a,int b,int c){
	int la=query(a,b),lb=query(b,c),lc=query(a,c),ans;
	if(la==lb) ans=lc;
	else if(la==lc) ans=lb;
	else ans=la;
	//return data(ans,as(dep[a]-dep[ans])+as(dep[b]-dep[ans])+as(dep[c]-dep[ans]));
	return data(ans,getdist(a,ans)+getdist(b,ans)+getdist(c,ans));
}
int main(){
	op();
	int n=read(),m=read(),u,v;
	rep(i,n-1) u=read(),v=read(),adde(u,v);
	clr(idx,0);clr(son,0);dep[1]=1;id[0]=0;
	dfs(1);DFS(1,1);
//	rep(i,n) printf("%d:%d %d %d %d %d %d\n",i,fa[i],son[i],size[i],dep[i],tp[i],idx[i]);
	rep(i,m) {
		data tmp=qsum(read(),read(),read());
		printf("%d %d\n",tmp.p,tmp.c);
	}
	return 0;
}

  

1787: [Ahoi2008]Meet 紧急集合

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 2268  Solved: 1028
[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

[Submit][Status][Discuss]
posted @ 2016-07-13 09:55  BBChq  阅读(157)  评论(0编辑  收藏  举报