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