码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1787 [AHOI2008] Meet 紧急集合

时间:2015-12-26 15:08:27      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1787

Description

技术分享

Input

技术分享

Output

技术分享

 

LCA水过

三个点两两求LCA,若有其中两个LCA一样“集合点”就是第三个LCA

多加inline有用处,DFS改BFS对效率没有什么提高

从上到下依次是DFS(小改),BFS,DFS

技术分享

DFS Version

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #define rep(i,l,r) for(int i=l; i<=r; i++)
 6 #define clr(x,y) memset(x,y,sizeof(x))
 7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
 8 using namespace std;
 9 const int INF = 0x3f3f3f3f;
10 const int maxn = 500010;
11 struct Edge{
12     Edge *pre; int to;
13 }edge[maxn<<1];
14 Edge *last[maxn],*pt;
15 int n,m,x,y,z,depth[maxn],fa[maxn][19];
16 bool vis[maxn];
17 inline int read(){
18     int ans = 0, f = 1;
19     char c = getchar();
20     while (!isdigit(c)){
21         if (c == -) f = -1;
22         c = getchar();
23     }
24     while (isdigit(c)){
25         ans = ans * 10 + c - 0;
26         c = getchar();
27     }
28     return ans * f;
29 }
30 inline void addedge(int x,int y){
31     pt->pre = last[x]; pt->to = y; last[x] = pt++;
32 }
33 void dfs(int x){
34     vis[x] = 1;
35     rep(i,1,18){
36         if (depth[x] < (1 << i)) break;
37         fa[x][i] = fa[fa[x][i-1]][i-1];
38     }
39     travel(x){
40         if (vis[p->to]) continue;
41         depth[p->to] = depth[x] + 1;
42         fa[p->to][0] = x;
43         dfs(p->to);
44     }
45 }
46 inline int lca(int x,int y){
47     if (depth[x] < depth[y]) swap(x,y);
48     int t = depth[x] - depth[y];
49     rep(i,0,18) if (t & (1 << i)) x = fa[x][i];
50     if (x == y) return x;
51     for(int i=18; i>=0; i--) if (fa[x][i] != fa[y][i]){
52         x = fa[x][i]; y = fa[y][i];
53     }
54     return fa[x][0];
55 }
56 inline int calc(int x,int y){
57     return depth[x] + depth[y] - (depth[lca(x,y)] << 1);
58 }
59 inline void solve(int x,int y,int z){
60     int l1 = lca(x,y), l2 = lca(y,z), l3 = lca(x,z), t;
61     if (l1 == l2) t = l3; else if (l2 == l3) t = l1; else t = l2;
62     int ans = calc(x,t) + calc(y,t) + calc(z,t);
63     printf("%d %d\n",t,ans);
64 }
65 int main(){
66     n = read(); m = read(); clr(last,0); pt = edge;
67     rep(i,1,n-1){
68         x = read(); y = read(); addedge(x,y); addedge(y,x);
69     }
70     clr(vis,0); dfs(1);
71     rep(i,1,m){
72         x = read(); y = read(); z = read(); solve(x,y,z);
73     }
74     return 0;
75 }
View Code

BFS Version

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <queue>
 6 #define rep(i,l,r) for(int i=l; i<=r; i++)
 7 #define clr(x,y) memset(x,y,sizeof(x))
 8 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
 9 using namespace std;
10 const int INF = 0x3f3f3f3f;
11 const int maxn = 500010;
12 struct Edge{
13     Edge *pre; int to;
14 }edge[maxn<<1];
15 Edge *last[maxn],*pt;
16 int n,m,x,y,z,depth[maxn],fa[maxn][19];
17 bool vis[maxn];
18 queue <int> q;
19 inline int read(){
20     int ans = 0, f = 1;
21     char c = getchar();
22     while (!isdigit(c)){
23         if (c == -) f = -1;
24         c = getchar();
25     }
26     while (isdigit(c)){
27         ans = ans * 10 + c - 0;
28         c = getchar();
29     }
30     return ans * f;
31 }
32 inline void addedge(int x,int y){
33     pt->pre = last[x]; pt->to = y; last[x] = pt++;
34 }
35 inline void bfs(){
36     clr(vis,0); q.push(1); depth[1] = 0;
37     while (!q.empty()){
38         int now = q.front(); q.pop();
39         if (vis[now]) continue;
40         vis[now] = 1;
41         rep(i,1,18){
42             if (depth[now] < (1 << i)) break;
43             fa[now][i] = fa[fa[now][i-1]][i-1];
44         }
45         travel(now){
46             if (vis[p->to]) continue;
47             depth[p->to] = depth[now] + 1;
48             fa[p->to][0] = now;
49             q.push(p->to);
50         }
51     }
52 }
53 inline int lca(int x,int y){
54     if (depth[x] < depth[y]) swap(x,y);
55     int t = depth[x] - depth[y];
56     rep(i,0,18) if (t & (1 << i)) x = fa[x][i];
57     for(int i=18; i>=0; i--) if (fa[x][i] != fa[y][i]){
58         x = fa[x][i]; y = fa[y][i];
59     }
60     if (x == y) return x;
61     return fa[x][0];
62 }
63 inline int calc(int x,int y){
64     return depth[x] + depth[y] - (depth[lca(x,y)] << 1);
65 }
66 inline void solve(int x,int y,int z){
67     int l1 = lca(x,y), l2 = lca(y,z), l3 = lca(x,z), t;
68     if (l1 == l2) t = l3; else if (l2 == l3) t = l1; else t = l2;
69     int ans = calc(x,t) + calc(y,t) + calc(z,t);
70     printf("%d %d\n",t,ans);
71 }
72 int main(){
73     n = read(); m = read(); clr(last,0); pt = edge;
74     rep(i,1,n-1){
75         x = read(); y = read(); addedge(x,y); addedge(y,x);
76     }
77     bfs();
78     rep(i,1,m){
79         x = read(); y = read(); z = read(); solve(x,y,z);
80     }
81     return 0;
82 }
View Code

 

BZOJ1787 [AHOI2008] Meet 紧急集合

标签:

原文地址:http://www.cnblogs.com/jimzeng/p/bzoj1787.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!