hdoj 2586 <LCA转RMQ算法--学习之路>
2016-08-04 10:30
393 查看
题目链接: hdoj 2586
思路:
先找一点作为起点通过DFS回溯记录每次DFS的点数(就是从根节点遍历所有点的去路和回来时的路)
用vis [ ] 数组记录每次走过的是哪一个点--
用D [ ] 来对应vis [ ] 数组上的点的深度(与根节点的距离)
用R [ ] 来记录每个点第一次出现的位置(两点的最初位置之间(含他们自身)的点中深度最小的点就是他们的最近祖先)
然后查找RMQ算法就可以查到最近祖先了---
样例:
![](https://img-blog.csdn.net/20160804105022239?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
我这个程序是让n当根节点--(因为这一题让1当根节点,,代码错的也会过--不便于学习新知识--(这题数据太弱))
看倒数第二行:回溯的顺序就是13-10-12-10-7------
最后一行就是回溯的每个位置的点的深度(用RMQ时,就是根据这个比较的)
倒数第四行是每个点第一次出现的位置--
比如求3和4的最近祖先时:
3第一次出现在8的位置,4是18的位置--然后我们在最后一行8-18中找最小的深度()
找到最小深度4--再看倒数第二行发现对应的是3----就是说明点3是3和4的最近祖先
回溯过程图:
![](https://img-blog.csdn.net/20160804110907493?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
代码上的中间值便于理解这个方法,所以就没有删除--
代码:
思路:
先找一点作为起点通过DFS回溯记录每次DFS的点数(就是从根节点遍历所有点的去路和回来时的路)
用vis [ ] 数组记录每次走过的是哪一个点--
用D [ ] 来对应vis [ ] 数组上的点的深度(与根节点的距离)
用R [ ] 来记录每个点第一次出现的位置(两点的最初位置之间(含他们自身)的点中深度最小的点就是他们的最近祖先)
然后查找RMQ算法就可以查到最近祖先了---
样例:
我这个程序是让n当根节点--(因为这一题让1当根节点,,代码错的也会过--不便于学习新知识--(这题数据太弱))
看倒数第二行:回溯的顺序就是13-10-12-10-7------
最后一行就是回溯的每个位置的点的深度(用RMQ时,就是根据这个比较的)
倒数第四行是每个点第一次出现的位置--
比如求3和4的最近祖先时:
3第一次出现在8的位置,4是18的位置--然后我们在最后一行8-18中找最小的深度()
找到最小深度4--再看倒数第二行发现对应的是3----就是说明点3是3和4的最近祖先
回溯过程图:
代码上的中间值便于理解这个方法,所以就没有删除--
代码:
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define MA 420000 int n,m; struct node{ int to,w,next; }edge[MA*2]; int head[MA]; int D[MA];//深度 int R[MA];//每个点第一次出现的位置 int QM[MA][33]; int vis[MA*2],kp;//vis记录第i个位置的数 int dis[MA]; void bfs(int now,int fa,int chang) { dis[now]=chang; for (int j=head[now];j!=-1;j=edge[j].next) { if (edge[j].to==fa) continue; bfs(edge[j].to,now,chang+edge[j].w); } } void DFS(int now,int fa,int deep) { D[kp]=deep; R[now]=kp; vis[kp++]=now; for (int j=head[now];j!=-1;j=edge[j].next) { if (edge[j].to==fa) continue; DFS(edge[j].to,now,deep+1); D[kp]=deep; vis[kp++]=now; } } int main() { int t;scanf("%d",&t); while (t--) { scanf("%d%d",&n,&m); int a,b,c; for (int i=1;i<=n;i++) head[i]=-1; for (int i=0;i<n-1;i++) { scanf("%d%d%d",&a,&b,&c); edge[i*2].to=b;edge[i*2].w=c; edge[i*2].next=head[a]; head[a]=i*2; edge[i*2+1].to=a;edge[i*2+1].w=c; edge[i*2+1].next=head[b]; head[b]=i*2+1; } kp=1; bfs(n,-1,0); DFS(n,-1,1); /* for (int i=1;i<=n;i++) printf("%4d",i);printf("\n"); for (int i=1;i<=n;i++) printf("%4d",R[i]);printf("\n"); for (int i=1;i<kp;i++) printf("%4d",i);printf("\n");*/ for (int i=1;i<kp;i++) { // printf("%4d",vis[i]); QM[i][0]=i; } /* printf("\n"); for (int i=1;i<kp;i++) printf("%4d",D[i]); printf("\n");*/ int nn=kp-1; int p=log2(nn); for (int i=1;i<=p;i++) for (int j=1;j+(1<<i)-1<=nn;j++) { int aa=QM[j][i-1]; int bb=QM[j+(1<<(i-1))][i-1]; // printf("%d %d %d %d 66666666666\n",aa,bb,D[aa],D[bb]); if (D[aa]<=D[bb]) QM[j][i]=aa; else QM[j][i]=bb; // printf("%d %d %d\n",j,i,QM[j][i]); } /* printf("\n"); for (int i=1;i<=n;i++) printf("%4d\n",dis[i]); */ while (m--) { scanf("%d%d",&a,&b); int aa=min(R[a],R[b]); int bb=max(R[a],R[b]); // printf("%d %d 9999999999999\n",aa,bb); int pp=log2(bb+1-aa); int aaa=QM[aa][pp]; int bbb=QM[bb+1-(1<<pp)][pp]; // c=min(QM[aa][pp],QM[bb+1-(1<<pp)][pp]); // printf("%d %d 666\n",aaa,bbb); if (D[aaa]<=D[bbb]) c=aaa; else c=bbb; // printf("%d\n",c); c=vis[c]; // printf("ans : %d\n",dis[a]+dis[b]-2*dis[c]); printf("%d\n",dis[a]+dis[b]-2*dis[c]); } } return 0; } /*2 13 13 1 2 1 1 3 1 1 4 1 3 5 1 3 6 1 3 7 1 6 8 1 6 9 1 7 10 1 7 11 1 10 12 1 10 13 1*/
相关文章推荐
- <收藏> 我的算法学习之路
- android <初级篇> 发送短信(调用已有接口)——菜鸟的学习之路
- Vim学习之路--解决<C-a>(Ctrl+a)在gvim for windows上不起作用
- RMQ转换成LCA <O(N), O(1)>
- <<The C Programming Language>>学习之路-练习题参考答案 1-9
- 本文专注于<递归算法和分治思想>[胖虎学习算法系列]
- <<The C Programming Language>>学习之路-练习题参考答案 1-3
- <<The C Programming Language>>学习之路-练习题参考答案 1-2
- <<The C Programming Language>>学习之路-练习题参考答案 1-12
- <<The C Programming Language>>学习之路-练习题参考答案 1-7
- OpenCV 2 学习笔记(11): 算法的基本设计模式<2>:使用Controller
- <<The C Programming Language>>学习之路-练习题参考答案 1-4
- <算法导论>学习笔记(3)--递归树求递归算法时间复杂度
- <<The C Programming Language>>学习之路-练习题参考答案 1-5
- 菜鸟的Hadoop学习之路系列<二>:Hadoop集群构成和HDFS
- 推荐引擎算法学习导论-(协同过滤、聚类、分类、模糊和精确k-means算法等)<转>
- android <初级篇> 界面布局<一> ——菜鸟的学习之路
- <<The C Programming Language>>学习之路-练习题参考答案 1-10
- <<The C Programming Language>>学习之路-练习题参考答案 1-1
- <<The C Programming Language>>学习之路-练习题参考答案 1-6