POJ 1330 Nearest Common Ancestors【LCA】
2016-03-24 22:49
501 查看
题目链接:
http://poj.org/problem?id=1330题意:
裸的LCA代码:
倍增:
#include<iostream> #include<cstring> using namespace std; const int maxn = 10005; const int maxm = 20; struct Edge{int to, next;}; Edge edge[maxn * 2]; int head[maxn], tot; int pa[maxm][maxn]; int dept[maxn], in[maxn]; int root, V; void add_edge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void initedge() { tot = 0; memset(head, -1, sizeof(head)); } //DFS预处理所有结点的深度和父节点 void dfs(int v, int p, int d) { pa[0][v] = p; dept[v] = d; for(int i = head[v]; i != -1; i = edge[i].next){ int u = edge[i].to; if(u == p) continue; dfs(u, v, d + 1); } } void init() { dfs(root, -1, 0); //预处理祖先,向上走2^i所到的结点 for(int i = 0; i < maxm - 1; i++){ for(int j = 1; j <= V; j++){ if(pa[i][j] < 0) pa[i + 1][j] = -1; else pa[i + 1][j] = pa[i][pa[i][j]]; } } } int lca(int u, int v) { //让u和v 向上走到同一高度 if(dept[u] > dept[v]) swap(u, v); for(int i = 0; i < maxm; i++){ if((dept[v] - dept[u]) >>i &1) v = pa[i][v]; } if(u == v) return u; //二分搜索计算lca for(int i = maxm - 1; i >= 0; i--){ if(pa[i][u] != pa[i][v]){ u = pa[i][u]; v = pa[i][v]; } } return pa[0][u]; } int main(void) { int T;cin>>T; int u, v; while(T--){ cin>>V; initedge(); memset(in, 0, sizeof(in)); for(int i = 1; i < V; i++){ cin>>u>>v; add_edge(u, v); add_edge(v, u); in[v] = 1; } for(root = 1; root <= V; root++){ if(!in[root]) break; } init(); cin>>u>>v; cout<<lca(u, v)<<endl;; } return 0;
RMQ:
(照着bin神的模板敲的#include<iostream> #include<cstring> #include<cmath> using namespace std; const int maxn = 10005; const int maxm = 20; struct Edge{int to, next;}; Edge edge[maxn * 2]; int head[maxn], tot; int pa[maxm][maxn]; int dept[maxn], in[maxn]; int root, V, cnt; int vs[maxn * 2], id[maxn]; int rmq[2 * maxn]; void add_edge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void initedge() { tot = 0; memset(head, -1, sizeof(head)); } struct ST { int lg[2 * maxn]; int dp[2 * maxn][20];//最小值对应下标 void init(int n){ lg[0] = -1; for(int i = 1; i <= n; i++){ lg[i] = ((i & (i - 1)) == 0)?lg[i - 1] + 1:lg[i - 1]; dp[i][0] = i; } for(int j = 1; j <= lg ; j++){ for(int i = 1; i + (1<<j) - 1 <= n; i++){ if(rmq[dp[i][j - 1]] < rmq[dp[i + (1<<(j - 1))][j - 1]]) dp[i][j] = dp[i][j - 1]; else dp[i][j] = dp[i + (1<<(j - 1))][j - 1]; } } } int query(int a, int b){ if(a > b) swap(a, b); int k = lg[b - a + 1] ; // cout<<b<<' '<<a<<endl; if(rmq[dp[a][k]] <= rmq[dp[b - (1<<k) + 1][k]]) return dp[a][k]; else return dp[b - (1<<k) + 1][k]; } }; ST st; //vs dfs的访问顺序 void dfs(int u, int pre, int dept) { vs[++cnt] = u; rmq[cnt] = dept; id[u] = cnt; int fro = head[u]; while(fro != -1){ dfs(edge[fro].to, u, dept + 1); fro = edge[fro].next; vs[++cnt] = u; rmq[cnt] = dept; } } void init() { cnt = 0; dfs(root, root, 0); st.init(2 * V - 1); } int lca(int u, int v) { return vs[st.query(id[u], id[v])]; } int main(void) { int T;cin>>T; int u, v; while(T--){ cin>>V; initedge(); memset(in, 0, sizeof(in)); for(int i = 1; i < V; i++){ cin>>u>>v; add_edge(u, v); in[v] = 1; } for(root = 1; root <= V; root++){ if(!in[root]) break; } init(); cin>>u>>v; cout<<lca(u, v)<<endl;; } return 0; }
相关文章推荐
- POJ 1330 Nearest Common Ancestors【LCA】
- UVALive 7528(2015德黑兰区域赛) Beehive
- 小学生算数测试
- SSH框架整合发现的问题,必须放置在Spring中配置
- xss漏洞利用
- 服务端PHP设置cookie,客户端未生效
- 服务端PHP设置cookie,客户端未生效
- ubuntu12.04安装nginx
- Leetcode #22 Generate Parentheses 创建括号 解题报告
- 我是一只新晋程序狗
- 网络流(最大流):COGS 28 [NOI2006] 最大获利
- 安装ubuntu14.04
- 【CV】CVPR2015_A Discriminative CNN Video Representation for Event Detection
- 树状数组的小总结
- 5 分钟上手 ECharts(echart官网转载)
- 用程序打印万年历
- 字符串分离方法
- RSA 数字签名 免密码登录
- PHP为什么会被认为是草根语言?
- 泛型(三)