wenbao与LCA
----------------------------------------------------------------------------------------------------------------
dfs+st(在线处理)
模板
1 const int maxn = 3e5+10; 2 int n; 3 4 struct adjs { 5 int to, next; 6 } ad[maxn<<1]; 7 8 int head[maxn], adcnt; 9 10 void adjs_init() { 11 for(int i = 1; i <= n; i++) head[i] = -1, vis[i] = false; 12 adcnt = 0; 13 } 14 15 void add_edge(int a, int b) { 16 ad[adcnt].next = head[a]; 17 ad[adcnt].to = b; 18 head[a] = adcnt++; 19 } 20 21 int S; 22 int a[maxn]; 23 24 int dep[maxn]; 25 26 int dfs_pre[maxn*2]; 27 int pw[maxn*2]; 28 int G[maxn]; 29 int dfs_clk; 30 31 void init() { 32 pw[1] = 0; 33 for(int i = 2; i < maxn*2; i++) pw[i] = pw[i-1] + !(i&(i-1)); 34 } 35 36 struct ST { 37 int N; 38 int T[23][maxn*2]; 39 40 void init(int _N, int *arr) { 41 N = _N; 42 for(int i = 1; i <= N; i++) T[0][i] = arr[i]; 43 } 44 45 inline int _max(int x,int y) { 46 if(dep[x] < dep[y]) return x; 47 else return y; 48 } 49 50 void update() { 51 for(int i = 1; i <= pw[N]; i++) { 52 for(int j = 1; j+(1<<i)-1 <= N; j++) { 53 T[i][j] = _max(T[i-1][j], T[i-1][j+(1<<(i-1))]); 54 } 55 } 56 } 57 58 int LCA(int x, int y) { 59 if(x > y) swap(x, y); 60 int p = pw[y-x+1]; 61 return _max(T[p][x], T[p][y-(1<<p)+1]); 62 } 63 } st; 64 65 66 void dfs(int u, int fa) { 67 // cout << u << "***" << fa << endl; 68 dep[u] = dep[fa] + 1; 69 dfs_pre[++dfs_clk] = u; 70 G[u] = dfs_clk; 71 for(int i = head[u]; ~i; i = ad[i].next) { 72 int v = ad[i].to; 73 if(v == fa) continue; 74 dfs(v, u); 75 dfs_pre[++dfs_clk] = u; 76 } 77 } 78 79 int dis(int x, int y) { 80 int lca = st.LCA(G[x], G[y]); 81 return dep[x] + dep[y] - dep[lca] - dep[lca]; 82 } 83 84 int main() { 85 init(); 86 scanf("%d", &n); 87 for(int i = 1; i < n; ++i) { 88 scanf("%d%d", &x, &y); 89 add_edge(x, y), add_edge(y, x); 90 } 91 dfs_clk = 0; 92 dfs(1, 0); 93 // cout<<"**"<<endl; 94 st.init(dfs_clk, dfs_pre); 95 st.update(); 96 scanf("%d", &q); 97 while(q--) { 98 scanf("%d%d", &x, &y); 99 printf("%d\n", dis(x, y)); 100 } 101 }
---------------
http://poj.org/problem?id=1330
求LCA
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 const int maxn = 3e5+10; 6 int n; 7 bool vis[maxn]; 8 9 struct adjs { 10 int to, next; 11 } ad[maxn<<1]; 12 13 int head[maxn], adcnt; 14 15 void adjs_init() { 16 for(int i = 1; i <= n; i++) head[i] = -1, vis[i] = false; 17 adcnt = 0; 18 } 19 20 void add_edge(int a, int b) { 21 ad[adcnt].next = head[a]; 22 ad[adcnt].to = b; 23 head[a] = adcnt++; 24 } 25 26 int S; 27 int a[maxn]; 28 29 int dep[maxn]; 30 31 int dfs_pre[maxn*2]; 32 int pw[maxn*2]; 33 int G[maxn]; 34 int dfs_clk; 35 36 void init(){ 37 pw[1]=0; 38 for(int i=2; i<maxn*2; i++) pw[i] = pw[i-1] + !(i&(i-1)); 39 } 40 41 struct ST { 42 int N; 43 int T[23][maxn*2]; 44 45 void init(int _N, int *arr) { 46 N=_N; 47 for(int i = 1; i <= N; i++) T[0][i] = arr[i]; 48 } 49 50 inline int _max(int x,int y) { 51 if(dep[x] < dep[y]) return x; 52 else return y; 53 } 54 55 void update() { 56 for(int i = 1; i <= pw[N]; i++) { 57 for(int j = 1; j+(1<<i)-1 <= N; j++) { 58 T[i][j] = _max(T[i-1][j], T[i-1][j+(1<<(i-1))]); 59 } 60 } 61 } 62 63 int LCA(int x, int y) { 64 if(x > y) swap(x, y); 65 int p = pw[y-x+1]; 66 return _max(T[p][x], T[p][y-(1<<p)+1]); 67 } 68 } st; 69 70 71 void dfs(int u, int fa) { 72 dep[u] = dep[fa] + 1; 73 dfs_pre[++dfs_clk] = u; 74 G[u] = dfs_clk; 75 for(int i = head[u]; ~i; i = ad[i].next) { 76 int v = ad[i].to; 77 if(v == fa) continue; 78 dfs(v, u); 79 dfs_pre[++dfs_clk] = u; 80 } 81 } 82 83 84 int main() { 85 init(); 86 int t; 87 scanf("%d", &t); 88 while(t--) { 89 scanf("%d", &n); 90 adjs_init(); 91 int x, y; 92 for(int i = 1; i < n; i++) { 93 scanf("%d%d", &x, &y); 94 add_edge(x,y); 95 add_edge(y,x); 96 vis[y] = true; 97 } 98 int id; 99 for(int i = 1; i <= n; ++i){ 100 if(!vis[i]){ 101 id = i; 102 break; 103 } 104 } 105 dfs_clk = 0; 106 dfs(id, 0); 107 //cout<<"**"<<endl; 108 st.init(dfs_clk, dfs_pre); 109 st.update(); 110 scanf("%d%d", &x, &y); 111 printf("%d\n", st.LCA(G[x], G[y])); 112 } 113 }
------------------------------------
求LCA
http://hihocoder.com/problemset/problem/1069
1 #include <iostream> 2 #include <algorithm> 3 #include <map> 4 #include <string> 5 #include <string.h> 6 using namespace std; 7 8 const int maxn = 1e5+10; 9 map<string, int> m; 10 string mm[maxn]; 11 int n; 12 struct adjs { 13 int to, next; 14 } ad[maxn<<1]; 15 int head[maxn], adcnt; 16 17 bool vis[maxn]; 18 19 void adjs_init() { 20 for(int i = 1; i < maxn; i++) head[i] = -1, vis[i] = false; 21 adcnt = 0; 22 } 23 void add_edge(int a, int b) { 24 ad[adcnt].next = head[a]; 25 ad[adcnt].to = b; 26 head[a] = adcnt++; 27 } 28 29 int S; 30 int a[maxn]; 31 32 int dep[maxn]; 33 34 int dfs_pre[maxn*2]; 35 int pw[maxn*2]; 36 int G[maxn]; 37 int dfs_clk; 38 39 void init() { 40 pw[1]=0; 41 for(int i=2; i<maxn*2; i++) pw[i] = pw[i-1] + !(i&(i-1)); 42 } 43 44 struct ST { 45 int N; 46 int T[23][maxn*2]; 47 48 void init(int _N, int *arr) { 49 N=_N; 50 for(int i = 1; i <= N; i++) T[0][i] = arr[i]; 51 } 52 53 inline int _max(int x,int y) { 54 if(dep[x] < dep[y]) return x; 55 else return y; 56 } 57 58 void update() { 59 for(int i = 1; i <= pw[N]; i++) { 60 for(int j = 1; j+(1<<i)-1 <= N; j++) { 61 T[i][j] = _max(T[i-1][j], T[i-1][j+(1<<(i-1))]); 62 } 63 } 64 } 65 66 int LCA(int x, int y) { 67 if(x > y) swap(x, y); 68 int p = pw[y-x+1]; 69 return _max(T[p][x], T[p][y-(1<<p)+1]); 70 } 71 } st; 72 73 74 void dfs(int u, int fa) { 75 dep[u] = dep[fa] + 1; 76 dfs_pre[++dfs_clk] = u; 77 G[u] = dfs_clk; 78 for(int i = head[u]; ~i; i = ad[i].next) { 79 int v = ad[i].to; 80 if(v == fa) continue; 81 dfs(v, u); 82 dfs_pre[++dfs_clk] = u; 83 } 84 } 85 86 char x[111], y[111]; 87 int main() { 88 init(); 89 int t; 90 while(~scanf("%d", &n)) { 91 m.clear(); 92 adjs_init(); 93 int num = 1; 94 for(int i = 0; i < n; i++) { 95 scanf("%s%s", x, y); 96 if(!m[x]) mm[num] = x, m[x] = num++; 97 if(!m[y]) mm[num] = y, m[y] = num++; 98 add_edge(m[x],m[y]); 99 add_edge(m[y],m[x]); 100 vis[m[y]] = true; 101 } 102 int id; 103 for(int i = 1; i <= n; ++i) { 104 if(!vis[i]) { 105 id = i; 106 break; 107 } 108 } 109 dfs_clk = 0; 110 dfs(id, 0); 111 st.init(dfs_clk, dfs_pre); 112 st.update(); 113 int t; 114 scanf("%d", &t); 115 for(int i = 0; i < t; ++i) { 116 scanf("%s%s", x, y); 117 printf("%s\n", mm[st.LCA(G[m[x]], G[m[y]])].c_str()); 118 } 119 } 120 }
--------------------------
http://codeforces.com/contest/832/problem/D
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 const int maxn = 3e5+10; 6 int n, q; 7 struct adjs { 8 int to, next; 9 } ad[maxn<<1]; 10 int head[maxn], adcnt; 11 12 13 void adjs_init() { 14 for(int i = 1; i <= n; i++) head[i] = -1; 15 adcnt = 0; 16 } 17 void add_edge(int a, int b) { 18 ad[adcnt].next = head[a]; 19 ad[adcnt].to = b; 20 head[a] = adcnt++; 21 } 22 23 int S; 24 int a[maxn]; 25 26 int dep[maxn]; 27 28 int dfs_pre[maxn*2]; 29 int pw[maxn*2]; 30 int G[maxn]; 31 int dfs_clk; 32 33 void init() { 34 pw[1]=0; 35 for(int i=2; i<maxn*2; i++) pw[i] = pw[i-1] + !(i&(i-1)); 36 } 37 38 struct ST { 39 int N; 40 int T[23][maxn*2]; 41 42 void init(int _N, int *arr) { 43 N=_N; 44 for(int i = 1; i <= N; i++) T[0][i] = arr[i]; 45 } 46 47 inline int _max(int x,int y) { 48 if(dep[x] < dep[y]) return x; 49 else return y; 50 } 51 52 void update() { 53 for(int i = 1; i <= pw[N]; i++) { 54 for(int j = 1; j+(1<<i)-1 <= N; j++) { 55 T[i][j] = _max(T[i-1][j], T[i-1][j+(1<<(i-1))]); 56 } 57 } 58 } 59 60 int LCA(int x, int y) { 61 if(x > y) swap(x, y); 62 int p = pw[y-x+1]; 63 return _max(T[p][x], T[p][y-(1<<p)+1]); 64 } 65 } st; 66 67 68 void dfs(int u, int fa) { 69 //cout<<u<<"**"<<fa<<endl; 70 dep[u] = dep[fa] + 1; 71 dfs_pre[++dfs_clk] = u; 72 G[u] = dfs_clk; 73 for(int i = head[u]; ~i; i = ad[i].next) { 74 int v = ad[i].to; 75 if(v == fa) continue; 76 dfs(v, u); 77 dfs_pre[++dfs_clk] = u; 78 } 79 } 80 81 int dis(int x, int y) { 82 int lca = st.LCA(G[x], G[y]); 83 return dep[x] + dep[y] - dep[lca] - dep[lca]; 84 } 85 86 int main() { 87 init(); 88 scanf("%d%d", &n, &q); 89 adjs_init(); 90 int x; 91 for(int i = 2; i <= n; ++i) { 92 scanf("%d", &x); 93 add_edge(x, i), add_edge(i, x); 94 } 95 dfs_clk = 0; 96 //cout<<"***"<<endl; 97 dfs(1, 0); 98 st.init(dfs_clk, dfs_pre); 99 st.update(); 100 while(q--) { 101 int a, b, c; 102 scanf("%d%d%d", &a, &b, &c); 103 int ab = dis(a, b), ac = dis(a, c), bc = dis(b, c); 104 printf("%d\n", (ab+ac+bc)/2-min(min(ab,bc),ac)+1); 105 } 106 return 0; 107 }
----------------------------------------------------------------------------------------------------------------
倍增(在线处理)
http://poj.org/problem?id=1330
1 #include <iostream> 2 #include <vector> 3 #include <string.h> 4 using namespace std; 5 const int maxn = 10009; 6 vector<int> v[maxn]; 7 int fa[maxn], f[21][maxn], dep[maxn], nu[maxn], t, n, root; 8 void d(int x){ 9 f[0][x] = fa[x]; 10 for(int i = 1; i <= 20; ++i){ 11 f[i][x] = f[i-1][f[i-1][x]]; 12 } 13 for(int i = 0; i < v[x].size(); ++i){ 14 int xx = v[x][i]; 15 if(xx != fa[x]){ 16 fa[xx] = x, dep[xx] = dep[x] + 1, d(xx); 17 } 18 } 19 } 20 int q(int x, int y){ 21 if(dep[x] < dep[y]) swap(x, y); 22 for(int i = 20; i >= 0; --i){ 23 if(dep[y] <= dep[f[i][x]]){ 24 x = f[i][x]; 25 } 26 } 27 if(x == y) return x; 28 for(int i = 20; i >= 0; --i){ 29 if(f[i][x] != f[i][y]){ 30 x = f[i][x], y = f[i][y]; 31 } 32 } 33 return f[0][x]; 34 } 35 void init(){ 36 root = 0; 37 memset(f, 0, sizeof(f)); 38 for(int i = 0; i <= n; ++i){ 39 v[i].clear(), dep[i] = 0, fa[i] = 0, nu[i] = 0; 40 } 41 } 42 int main(){ 43 scanf("%d", &t); 44 while(t--){ 45 scanf("%d", &n); 46 int x, y; 47 init(); 48 for(int i = 1; i < n; ++i){ 49 scanf("%d%d", &x, &y); 50 v[x].push_back(y), v[y].push_back(x); 51 nu[y]++; 52 } 53 while(nu[++root]); 54 fa[root] = root, dep[root] = 0; 55 d(root); 56 scanf("%d%d", &x, &y); 57 printf("%d\n", q(x, y)); 58 } 59 return 0; 60 }
------------------------------------------
http://codeforces.com/contest/832/problem/D
1 #include <iostream> 2 #include <string.h> 3 #include <vector> 4 using namespace std; 5 const int maxn = 1e5+10; 6 vector<int> v[maxn]; 7 int f[21][maxn], fa[maxn], dep[maxn]; 8 void d(int x){ 9 f[0][x] = fa[x]; 10 for(int i = 1; i <= 20; ++i){ 11 f[i][x] = f[i-1][f[i-1][x]]; 12 } 13 for(int i = 0; i < v[x].size(); ++i){ 14 int xx = v[x][i]; 15 if(xx != fa[x]){ 16 fa[xx] = x, dep[xx] = dep[x] + 1; 17 d(xx); 18 } 19 } 20 } 21 int q(int x, int y){ 22 int sum = dep[x] + dep[y], xx; 23 if(dep[x] < dep[y]) swap(x, y); 24 for(int i = 20; i >= 0; --i){ 25 if(dep[y] <= dep[f[i][x]]) x = f[i][x]; 26 } 27 if(x == y) xx = x; 28 else{ 29 for(int i = 20; i >= 0; --i){ 30 if(f[i][x] != f[i][y]){ 31 x = f[i][x], y = f[i][y]; 32 } 33 } 34 xx = f[0][x]; 35 } 36 return sum - 2*dep[xx]; 37 } 38 int main(){ 39 int n, m, x; 40 scanf("%d%d", &n, &m); 41 for(int i = 2; i <= n; ++i){ 42 scanf("%d", &x); 43 v[i].push_back(x), v[x].push_back(i); 44 } 45 fa[1] = 1, dep[1] = 0; 46 d(1); 47 while(m--){ 48 int a, b, c; 49 scanf("%d%d%d", &a, &b, &c); 50 int ab = q(a, b), ac = q(a, c), bc = q(b, c); 51 printf("%d\n", (ab+ac+bc)/2-min(min(ab, ac), bc)+1); 52 } 53 return 0; 54 }
----------------------------------------------------------------------------------------------------------------
tarjan(离线处理)
----------------------------
http://codevs.cn/problem/2370/
1 #include <iostream> 2 #include <string.h> 3 #include <vector> 4 #include <stdio.h> 5 using namespace std; 6 const int maxn = 50000; 7 int t, n, m, f[maxn], dis[maxn], sum[75009]; 8 bool vis[maxn]; 9 vector<int> v[maxn], w[maxn], q[maxn], num[maxn]; 10 void init(){ 11 for(int i = 0; i <= n; ++i){ 12 v[i].clear(), w[i].clear(), q[i].clear(), num[i].clear(); 13 f[i] = i, vis[i] = false; 14 } 15 } 16 int F(int x){ 17 return f[x] == x ? x : f[x] = F(f[x]); 18 } 19 void uni(int x, int y){ 20 int xx = F(x), yy = F(y); 21 if(xx != yy) f[yy] = xx; 22 } 23 void tr(int x, int cnt){ 24 vis[x] = true, dis[x] = cnt; 25 for(int i = 0; i < v[x].size(); ++i){ 26 int xx = v[x][i]; 27 if(vis[xx]) continue; 28 tr(xx, cnt+w[x][i]); 29 uni(x, xx); 30 } 31 for(int i = 0; i < q[x].size(); ++i){ 32 int xx = q[x][i]; 33 if(vis[xx]){ 34 sum[num[x][i]] = dis[x] + dis[xx] - 2*dis[F(xx)]; 35 } 36 } 37 } 38 int main(){ 39 scanf("%d", &n); 40 int x, y, ww; 41 init(); 42 for(int i = 1; i < n; ++i){ 43 scanf("%d%d%d", &x, &y, &ww); 44 v[x].push_back(y); 45 w[x].push_back(ww); 46 v[y].push_back(x); 47 w[y].push_back(ww); 48 } 49 scanf("%d", &m); 50 for(int i = 0; i < m; ++i){ 51 scanf("%d%d", &x, &y); 52 q[x].push_back(y); 53 q[y].push_back(x); 54 num[x].push_back(i); 55 num[y].push_back(i); 56 } 57 tr(1, 0); 58 for(int i = 0; i < m; ++i){ 59 printf("%d\n", sum[i]); 60 } 61 return 0; 62 }
---------------------
http://acm.hdu.edu.cn/showproblem.php?pid=2586
1 #include <iostream> 2 #include <string.h> 3 #include <vector> 4 using namespace std; 5 const int maxn = 40009; 6 int t, n, m, f[maxn], dis[maxn], sum[maxn]; 7 bool vis[maxn]; 8 vector<int> v[maxn], w[maxn], q[maxn], num[maxn]; 9 void init(){ 10 for(int i = 0; i <= n; ++i){ 11 v[i].clear(), w[i].clear(), q[i].clear(), num[i].clear(); 12 f[i] = i, vis[i] = false; 13 } 14 } 15 int F(int x){ 16 return f[x] == x ? x : f[x] = F(f[x]); 17 } 18 void uni(int x, int y){ 19 int xx = F(x), yy = F(y); 20 if(xx != yy) f[yy] = xx; 21 } 22 void tr(int x, int cnt){ 23 vis[x] = true, dis[x] = cnt; 24 for(int i = 0; i < v[x].size(); ++i){ 25 int xx = v[x][i]; 26 if(vis[xx]) continue; 27 tr(xx, cnt+w[x][i]); 28 uni(x, xx); 29 } 30 for(int i = 0; i < q[x].size(); ++i){ 31 int xx = q[x][i]; 32 if(vis[xx]){ 33 sum[num[x][i]] = dis[x] + dis[xx] - 2*dis[F(xx)]; 34 } 35 } 36 } 37 int main(){ 38 scanf("%d", &t); 39 while(t--){ 40 scanf("%d%d", &n, &m); 41 int x, y, ww; 42 init(); 43 for(int i = 1; i < n; ++i){ 44 scanf("%d%d%d", &x, &y, &ww); 45 v[x].push_back(y); 46 w[x].push_back(ww); 47 v[y].push_back(x); 48 w[y].push_back(ww); 49 } 50 for(int i = 0; i < m; ++i){ 51 scanf("%d%d", &x, &y); 52 q[x].push_back(y); 53 q[y].push_back(x); 54 num[x].push_back(i); 55 num[y].push_back(i); 56 } 57 tr(1, 0); 58 for(int i = 0; i < m; ++i){ 59 printf("%d\n", sum[i]); 60 } 61 } 62 return 0; 63 }
-----------------------------------------------------------
https://www.nowcoder.com/acm/contest/15/C
可以证明此题可以转化为求虚数的最长直径的一半(向上取整)
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 const int maxn = 3e5+10; 6 int n; 7 struct adjs { 8 int to, next; 9 } ad[maxn<<1]; 10 int head[maxn], adcnt; 11 void adjs_init() { 12 for(int i = 1; i <= n; i++) head[i] = -1; 13 adcnt = 0; 14 } 15 void add_edge(int a, int b) { 16 ad[adcnt].next = head[a]; 17 ad[adcnt].to = b; 18 head[a] = adcnt++; 19 } 20 21 int S; 22 int a[maxn]; 23 24 int dep[maxn]; 25 26 int dfs_pre[maxn*2]; 27 int pw[maxn*2]; 28 int G[maxn]; 29 int dfs_clk; 30 31 void init(){ 32 pw[1]=0; 33 for(int i=2; i<maxn*2; i++) pw[i] = pw[i-1] + !(i&(i-1)); 34 } 35 36 struct ST { 37 int N; 38 int T[23][maxn*2]; 39 40 void init(int _N, int *arr) { 41 N=_N; 42 for(int i = 1; i <= N; i++) T[0][i] = arr[i]; 43 } 44 45 inline int _max(int x,int y) { 46 if(dep[x] < dep[y]) return x; 47 else return y; 48 } 49 50 void update() { 51 for(int i = 1; i <= pw[N]; i++) { 52 for(int j = 1; j+(1<<i)-1 <= N; j++) { 53 T[i][j] = _max(T[i-1][j], T[i-1][j+(1<<(i-1))]); 54 } 55 } 56 } 57 58 int LCA(int x, int y) { 59 if(x > y) swap(x, y); 60 int p = pw[y-x+1]; 61 return _max(T[p][x], T[p][y-(1<<p)+1]); 62 } 63 } st; 64 65 66 void dfs(int u, int fa) { 67 dep[u] = dep[fa]+1; 68 dfs_pre[++dfs_clk] = u; 69 G[u] = dfs_clk; 70 71 for(int i = head[u]; ~i; i = ad[i].next) { 72 int v = ad[i].to; 73 if(v == fa) continue; 74 dfs(v, u); 75 dfs_pre[++dfs_clk] = u; 76 } 77 } 78 79 80 inline int CMP(const int x,const int y) { 81 return dep[x] > dep[y]; 82 } 83 84 int main() { 85 init(); 86 while(~scanf("%d",&n)) { 87 adjs_init(); 88 for(int i = 1; i < n; i++) { 89 int x, y; 90 scanf("%d", &x), scanf("%d", &y); 91 add_edge(x,y); 92 add_edge(y,x); 93 } 94 dfs_clk = 0; 95 dfs(1, 0); 96 st.init(dfs_clk, dfs_pre); 97 st.update(); 98 int Q; 99 scanf("%d", &Q); 100 while(Q--) { 101 scanf("%d", &S); 102 for(int i = 0; i < S; i++) scanf("%d", &a[i]); 103 sort(a, a+S, CMP); 104 int ans = 0, ntp, dist; 105 for(int i = 1; i < S; i++) { 106 ntp = st.LCA(G[a[0]],G[a[i]]); 107 dist = dep[a[0]] + dep[a[i]] - dep[ntp] - dep[ntp]; 108 dist = (dist+1)>>1; 109 if(ans < dist) ans = dist; 110 } 111 printf("%d\n", ans); 112 } 113 } 114 }
------------------------------------------------------------
只有不断学习才能进步!