[BZOJ 1787 & 1832] [Ahoi2008] Meet 紧急集合

1787 & 1832: [Ahoi2008]Meet 紧急集合

Time Limit: 10 Sec / 20 Sec
Memory Limit: 162 MB

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

【题解】
可以证明,最小的点一定在三点中任意两点的LCA上,那么只要用倍增来求下LCA即可。
注意,本题树根节点在1,因为你不知道父亲孩子的关系所以需要建两条边,BFS加一个判断就好
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int to[1000010],next[1000010],dep[1000010];
 4 int p[500010][21],n,m,head[500010],root,tot=0;
 5 bool deg[500010];
 6 inline void bfs(int root) {
 7     queue<int> Q;
 8     p[root][0]=root; dep[root]=0;
 9     Q.push(root);
10     while(!Q.empty()) {
11         int u=Q.front();Q.pop();
12         for (int i=1;i<=20;++i) p[u][i]=p[p[u][i-1]][i-1];
13         for (int i=head[u];i!=-1;i=next[i])
14             if(to[i]!=p[u][0]) {
15                 int v=to[i];
16                 dep[v]=dep[u]+1; p[v][0]=u;
17                 Q.push(v);
18             }
19     }
20 }
21 inline int lca(int x,int y) {
22     if(dep[x]<dep[y]) {int t=x;x=y;y=t;}
23     for (int i=20;i>=0;--i) if((dep[x]-dep[y]) & (1<<i)) x=p[x][i];
24     if(x==y) return x;
25     for (int i=20;i>=0;--i) 
26         if(p[x][i]!=p[y][i])  
27             x=p[x][i],y=p[y][i];  
28     return p[x][0];  
29 }
30 inline int getdist(int u,int v) {
31     return dep[u]+dep[v]-(dep[lca(u,v)]<<1);
32 }
33 int main() {
34     memset(head,-1,sizeof(head));
35     memset(deg,0,sizeof(deg));
36     scanf("%d%d",&n,&m);
37     for (int i=1;i<=n-1;++i) {
38         int u,v;
39         scanf("%d%d",&u,&v);
40         to[tot]=v;
41         next[tot]=head[u];
42         head[u]=tot++;
43         int t=u;u=v;v=t;
44         to[tot]=v;
45         next[tot]=head[u];
46         head[u]=tot++;
47     }
48     bfs(1);
49     int a1,a2,a3,b1,b2,b3,u,v,w;
50     while(m--) {
51         scanf("%d%d%d",&u,&v,&w);
52         a1=lca(u,v); b1=dep[u]+dep[v]-(dep[a1]<<1)+getdist(a1,w);
53         a2=lca(u,w); b2=dep[u]+dep[w]-(dep[a2]<<1)+getdist(a2,v);
54         a3=lca(v,w); b3=dep[v]+dep[w]-(dep[a3]<<1)+getdist(a3,u);
55         //printf("   %d %d\n",a1,b1);printf("   %d %d\n",a2,b2);printf("   %d %d\n",a3,b3);
56         if(b1<b2) {
57             if(b1<b3) printf("%d %d\n",a1,b1);
58             else printf("%d %d\n",a3,b3);
59         } else {
60             if (b2<b3)printf("%d %d\n",a2,b2);
61             else printf("%d %d\n",a3,b3);
62         }
63     }
64 }
View Code

计算距离的时候只需要dep[x]+dep[y]-dep[lca(x,y)]*2就好了。

BZOJ 26题了好开心WWW

这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
posted @ 2015-06-20 17:45  TonyFang  阅读(175)  评论(0编辑  收藏  举报