LCA 笔记

简述这几天的LCA 心得:

LCA有两种做法:离线 or 在线

先学的离线;

原理博客很多。

我写得两道题,已经模板。

HDU:http://acm.hdu.edu.cn/showproblem.php?pid=2586

HDU :http://acm.hdu.edu.cn/showproblem.php?pid=2874 2874;

之前一份板子:

 1 #pragma comment(linker, "/STACK:10240000000,10240000000")
 2
 3 #include<iostream>
 4 #include<stdio.h>
 5 #include<string.h>
 6 #include<cmath>
 7 #include<algorithm>
 8 #include<string>
 9 #include<vector>
10 using namespace std;
11
12 #define N 51111
13 struct node
14 {
15     int v,w;
16
17     node(int vv,int ww)
18     {
19        v=vv;
20        w=ww;
21     }
22 };
23 int f[N],dis[N],ans[N],vis[N],n;
24 vector<node>mp[N];
25 vector<node>q[N];
26
27 int find(int x)
28 {
29     if (f[x]!=x)  f[x]=find(f[x]);
30     return f[x];
31 }
32
33 void lca(int u)
34 {
35     for (int i=0;i<mp[u].size();i++)
36     {
37         int v=mp[u][i].v;
38         if (vis[v]) continue;
39         vis[v]=1;
40
41         dis[v]=dis[u]+mp[u][i].w;
42         lca(v);
43         f[v]=u;
44         for (int j=0;j<q[v].size();j++)
45         {
46             int c=q[v][j].v;
47             if (vis[c]&&ans[q[v][j].w]==-1)
48             {
49                 if (v==c) ans[q[v][j].w]=0;
50                 else ans[q[v][j].w]=dis[v]+dis[c]-2*dis[find(c)];
51             }
52         }
53     }
54 }
55
56 int main()
57 {
58     int T;
59     scanf("%d",&T);
60     while (T--)
61     {
62         int m;
63         scanf("%d%d",&n,&m);
64         for (int i=1;i<=n;i++)
65         {
66             mp[i].clear();
67             q[i].clear();
68             ans[i]=-1;
69             f[i]=i;
70             vis[i]=0;
71         }
72         for (int i=1;i<n;i++)
73         {
74             int a,b,c;
75             scanf("%d%d%d",&a,&b,&c);
76             mp[a].push_back(node(b,c));
77             mp[b].push_back(node(a,c));
78         }
79         for (int i=1;i<=m;i++)
80         {
81             int a,b;
82             scanf("%d%d",&a,&b);
83             q[a].push_back(node(b,i));
84             q[b].push_back(node(a,i));
85         }
86         vis[1]=1;
87         dis[1]=0;
88         lca(1);
89
90         for (int i=1;i<=m;i++)
91             printf("%d\n",ans[i]);
92     }
93     return 0;
94 }

是有问题的,但是数据弱所以没爆出来。

正确形式:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<string>
 7 #include<vector>
 8 using namespace std;
 9
10 #define N 51111
11 struct node
12 {
13     int v,w;
14
15     node(int vv,int ww)
16     {
17        v=vv;
18        w=ww;
19     }
20 };
21 int f[N],dis[N],ans[N],vis[N],n;
22 vector<node>mp[N];
23 vector<node>q[N];
24
25 int find(int x)
26 {
27     if (f[x]!=x)  f[x]=find(f[x]);
28     return f[x];
29 }
30
31 void lca(int u)
32 {
33     for (int i=0;i<mp[u].size();i++)
34     {
35         int v=mp[u][i].v;
36         if (vis[v]) continue;
37         vis[v]=1;
38
39         dis[v]=dis[u]+mp[u][i].w;
40         lca(v);
41         f[v]=u;
42     }
43         for (int j=0;j<q[u].size();j++)
44         {
45             int c=q[u][j].v;
46             if (vis[c]&&ans[q[u][j].w]==-1)
47             {
48                 if (u==c) ans[q[u][j].w]=0;
49                 else ans[q[u][j].w]=dis[u]+dis[c]-2*dis[find(c)];
50             }
51         }
52
53 }
54
55 int main()
56 {
57     int T;
58     scanf("%d",&T);
59     while (T--)
60     {
61         int m;
62         scanf("%d%d",&n,&m);
63         for (int i=1;i<=n;i++)
64         {
65             mp[i].clear();
66             q[i].clear();
67             ans[i]=-1;
68             f[i]=i;
69             vis[i]=0;
70         }
71         for (int i=1;i<n;i++)
72         {
73             int a,b,c;
74             scanf("%d%d%d",&a,&b,&c);
75             mp[a].push_back(node(b,c));
76             mp[b].push_back(node(a,c));
77         }
78         for (int i=1;i<=m;i++)
79         {
80             int a,b;
81             scanf("%d%d",&a,&b);
82             q[a].push_back(node(b,i));
83             q[b].push_back(node(a,i));
84         }
85         vis[1]=1;
86         dis[1]=0;
87         lca(1);
88
89         for (int i=1;i<=m;i++)
90             printf("%d\n",ans[i]);
91     }
92     return 0;
93 }

可以仔细体验差别。

因为 在其中吃了大亏。HDU 2874 (都是简单题)卡了三天 。想想算法没错 ,果然是板子的问题。

换一种写法也可以,询问在递归前面也可以。

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<string>
  7 #include<vector>
  8 using namespace std;
  9
 10 #define N 21111
 11 typedef long long ll;
 12 struct node
 13 {
 14     int v,w;
 15     node(int vv=0,int ww=0)
 16     {
 17        v=vv;
 18        w=ww;
 19     }
 20 };
 21
 22 int f[N];
 23 int ans[1110000],dis[N];
 24 int vis[N],mark[N];
 25
 26 vector<node>mp[N];
 27 vector<node>q[N];
 28
 29 int find(int x)
 30 {
 31     if (f[x]!=x)  f[x]=find(f[x]);
 32     return f[x];
 33 }
 34
 35 void lca(int u)
 36 {
 37
 38     for (int i=0;i<q[u].size();i++)
 39     {
 40         int c=q[u][i].v;
 41         int w=q[u][i].w;
 42         if (vis[c]&&ans[w]==-1&&mark[find(c)]!=1)
 43         {
 44             ans[w]=dis[u]+dis[c]-2*dis[find(c)];
 45         }
 46     }
 47
 48       for (int i=0;i<mp[u].size();i++)
 49     {
 50         int v=mp[u][i].v;
 51         if (vis[v]) continue;
 52         vis[v]=1;
 53         dis[v]=dis[u]+mp[u][i].w;
 54         lca(v);
 55         f[v]=u;
 56         /*
 57        for (int j=0;j<q[v].size();j++)
 58         {
 59             int c=q[v][j].v;
 60             int w=q[v][j].w;
 61             if (vis[c]&&ans[w]==-1&&mark[find(c)]!=1)
 62             {
 63                 // if (v==c) ans[w]=0;
 64                 // else
 65                  ans[w]=dis[v]+dis[c]-2*dis[find(c)];
 66             }
 67         }
 68         */
 69
 70     }
 71 }
 72
 73 int main()
 74 {
 75     // freopen("input.txt","r",stdin);
 76     // freopen("output1.txt","w",stdout);
 77      int n,m,C;
 78      while (scanf("%d%d%d",&n,&m,&C)!=EOF)
 79      {
 80         for (int i=0;i<=n;i++)
 81         {
 82             f[i]=i;
 83             mp[i].clear();
 84             q[i].clear();
 85             vis[i]=0;
 86             dis[i]=0;
 87             mark[i]=0;
 88         }
 89         for (int i=1;i<=C;i++) ans[i]=-1;
 90         for (int i=1;i<=m;i++)
 91         {
 92             int a,b,c;
 93             scanf("%d%d%d",&a,&b,&c);
 94             mp[a].push_back(node(b,c));
 95             mp[b].push_back(node(a,c));
 96         }
 97         for (int i=1;i<=C;i++)
 98         {
 99             int a,b;
100             scanf("%d%d",&a,&b);
101             q[a].push_back(node(b,i));
102             q[b].push_back(node(a,i));
103         }
104
105         for (int i=1;i<=n;i++)
106         if (!vis[i])
107         {
108             vis[i]=1;
109             dis[i]=0;
110             lca(i);
111             mark[i]=1;
112         }
113
114          for (int i=1;i<=n;i++)
115          for (int j=0;j<q[i].size();j++)
116          {
117              int u=i;
118              int v=q[i][j].v;
119              int w=q[i][j].w;
120              if (find(u)!=find(v)) ans[w]=-1;
121          }
122
123
124             for (int i=1;i<=C;i++)
125             if (ans[i]==-1) printf("Not connected\n");
126             else printf("%d\n",ans[i]);
127
128     }
129     return 0;
130 }
时间: 2024-08-08 13:20:31

LCA 笔记的相关文章

算法笔记--lca倍增算法

算法笔记 模板: vector<int>g[N]; vector<int>edge[N]; int anc[20][N]; int deep[N]; int h[N]; void dfs(int o,int u,int w) { if(u!=o)deep[u]=deep[o]+1,h[u]=h[o]+w; for(int j=0;j<g[u].size();j++) { if(g[u][j]!=o) { anc[0][g[u][j]]=u; for(int i=1;i<

LCA学习笔记

LCA学习笔记 http://dongxicheng.org/structure/lca-rmq/ http://blog.csdn.net/wendavidoi/article/details/50670052 dfs序 + st 树上倍增 Tarjan算法 题目 TBD 模板 TBD 原文地址:https://www.cnblogs.com/wuyuanyuan/p/8511682.html

poj1330 lca 最近公共祖先问题学习笔记

首先推荐两个博客网址: http://dongxicheng.org/structure/lca-rmq/ http://scturtle.is-programmer.com/posts/30055.html [转]tarjan算法的步骤是(当dfs到节点u时): 1 在并查集中建立仅有u的集合,设置该集合的祖先为u 1 对u的每个孩子v:    1.1 tarjan之    1.2 合并v到父节点u的集合,确保集合的祖先是u 2 设置u为已遍历 3 处理关于u的查询,若查询(u,v)中的v已遍

笔记:LCA最近公共祖先 Tarjan(离线)算法

LCA最近公共祖先 Tarjan他贱(离线)算法的基本思路及其算法实现 本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig/article/details/52336496 https://baike.baidu.com/item/最近公共祖先/8918834?fr=aladdin 最近公共祖先简称LCA(Lowest Common Ancesto

[笔记]LCA最近公共祖先---倍增在线算法

059M37853N虏3Jhttp://www.zcool.com.cn/collection/ZMTg2OTM5ODg=.html 痹o83RI世9EUS两http://www.zcool.com.cn/collection/ZMTg2OTQwMTY=.html 猩骋05K型51抡MChttp://www.zcool.com.cn/collection/ZMTg2OTQxMjg=.html 4辣腾膛且j匠9坝3凳W1http://www.zcool.com.cn/collection/ZMTg

面试高级算法梳理笔记

面试高级算法梳理笔记 1.1 说明 本篇为<挑战程序设计竞赛(第2版)>读书笔记系列,旨在: 梳理算法逻辑 探索优化思路 深入代码细节 1.2 目录 原文首发于个人博客Jennica.Space,按算法难度划分为初中高三个级别,详细目录及链接如下: 初级篇 穷竭搜索 贪心 动态规划 数据结构 图论 数论 中级篇 二分搜索 常用技巧 数据结构(二) 动态规划(二) 网络流 计算几何 高级篇 数论(二) 博弈论 图论(二) 常用技巧(二) 智慧搜索 分治 字符串 1.3 题解 配套习题及详解同步发

【Query处理学习笔记】搜索引擎查询推荐技术综述_中文信息学报2010_王斌

主要内容:对通用搜索引擎的查询推荐技术的方法.评价进行了总结 具体内容: "查询推荐"的不同英文叫法:Query Suggestion.Term Suggestion.Query Recommendation.Query Substitution.Query Rewriting 查询推荐的任务:找出和用户查询相似的query,以便更好地表达用户查询意图,供用户便捷输入 三种技术方法: 1. 基于文档的方法:通过处理query搜索出来的文档,以此作为反馈,进一步理解用户意图,扩充quer

支配树学习笔记

支配树(dominator tree) 学习笔记 学习背景 本来本蒟蒻都不知道有一个东西叫支配树……pkuwc前查某位的水表看见它的大名,甚感恐慌啊.不过好在pkuwc5道题(嗯?)都是概率期望计数,也不知是好还是不好,我在这些方面也只是不好不差……扯远了. 考挂之后也没什么心思干别的,想起支配树这个东西,于是打算学一下. 技能介绍(雾) 支配树是什么?不如直接讲支配树的性质,从性质分析它的定义. 先大概讲一下它是来求什么的. 问题:我们有一个有向图(可以有环),定下了一个节点为起点s.现在我们

带花树算法学习笔记

带花树算法学习笔记 难得yyb写了一个这么正式的标题 Q:为啥要学带花树这种东西啊? A:因为我太菜了,要多学点东西才能不被吊打 Q:为啥要学带花树这种东西啊? A:因为我做自己的专题做不动了,只能先去"预习"ppl的专题了 Q:为啥要学带花树这种东西啊? A:因为可以用来做题啊,比如某WC题目 先推荐一个很皮很皮的带花树讲解: 戳这里嗷 QaQ 言归正传 带花树的算法用来解决一般图的最大匹配问题 说起来,是不是想起来网络流里面的最小路径覆盖? 或者二分图的最大匹配的问题? 的确,带花