树链剖分。求任意三个点的最小集合距离。有一个结论。但是不会也可以枚举。注意如果是两棵子树中的点那么原来的计算方法就错了。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
",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
",tmp.p,tmp.c);
}
return 0;
}
1787: [Ahoi2008]Meet 紧急集合
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 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
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
