为什么以它为例,因为这个最水,LCA唯一黄题。

首先做两道并查集的练习(估计已经忘光了)。简单来说并查集就是认爸爸找爸爸的算法。先根据线索理认爸爸,然后查询阶段如果发现他们的爸爸相同,那就是联通一家的,不同就不是一家的。

两道简单例题

P1551 亲戚       P1536  村村通

以P1551 亲戚为例

题目背景

若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。

题目描述

规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。

输入格式

第一行:三个整数n,m,p,(n<=5000,m<=5000,p<=5000),分别表示有n个人,m个亲戚关系,询问p对亲戚关系。

以下m行:每行两个数Mi,Mj,1<=Mi,Mj<=N,表示Mi和Mj具有亲戚关系。

接下来p行:每行两个数Pi,Pj,询问Pi和Pj是否具有亲戚关系。

输出格式

P行,每行一个’Yes’或’No’。表示第i个询问的答案为“具有”或“不具有”亲戚关系

代码核心部分find函数:

int find(int num)
{
if(die[num]==num)
{
return num;
}
die[num]= find(die[num]);//记忆化,缩减递归产生的重复,找过的就记下来。
return die[num];
}

找到自己的爸爸的爸爸的爸爸……,然后找到根后用die[]记录下来。

完整代码

#include<cstdio>
#include<iostream>
using namespace std;
int n,m,p,c,d,die[];
int find(int num)
{
if(die[num]==num)//发现他自己主宰自己,直接返回他自己(递归的出口)
{
return num;
}
die[num]= find(die[num]);//如果不是,递归找他爸爸的爸爸
return die[num];
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=;i<=n;i++)
{
die[i]=i;
}
for(int i=;i<=m;i++)
{
scanf("%d%d",&c,&d);
die[find(c)]=find(d);//找到c的爸爸的爸爸,然后让c的爸爸认d的爸爸为爸爸…… 当然可以c和d反过来存。
} for(int i=;i<=p;i++)
{
scanf("%d%d",&c,&d);
if(find(c)==find(d))//查询一下他们的爸爸是不是同一人
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
}

P1536 村村通

题目描述

某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府 "村村通工程" 的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?

输入格式

输入包含若干组测试测试数据,每组测试数据的第一行给出两个用空格隔开的正整数,分别是城镇数目 nn 和道路数目 mm ;随后的 mm 行对应 mm 条道路,每行给出一对用空格隔开的正整数,分别是该条道路直接相连的两个城镇的编号。简单起见,城镇从 11 到 nn 编号。

注意:两个城市间可以有多条道路相通。

输出格式

对于每组数据,对应一行一个整数。表示最少还需要建设的道路数目。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,die[],c,d,e,f,ans;
int find(int num)
{
if (die[num]==num)return num;
return die[num]=find(die[num]);//还是记忆化,注意养成递归思考避免重复运算的习惯
}
int main()
{
while()
{
scanf("%d",&c);
if(c==)break;
for(int i=;i<=c;i++)die[i]=i;
ans=;
scanf("%d",&d);
for(int i=;i<d;i++)
{
scanf("%d%d",&e,&f);
die[find(e)]=find(f);
}
for(int i=;i<=c;i++)
{
if(die[i]==i)ans++;//统计多少自己管理自己的孤儿,每个孤儿需要一条道路
}
if(ans==){
printf("%d\n",);
}
else printf("%d\n",ans-);
} }

题目大致就是寻找有多少孤苦伶仃的孤儿,统计一下输出。和亲戚一题差不太多。

分割一下————————————————

以下是利用并查集理论寻找最近公共祖先。这种算法叫做Tarjan算法(读作塔珍,译作塔扬,是发明大佬的名字)

这只是简化版的裸LCA题,改天奉上复杂版的。

P5836 [USACO19DEC]Milk Visits S

题目描述请传送看洛谷。

题目的大体思路就是将有连接的同类奶牛用并查集的方式聚集起来,他们有共同的祖先。

然后查询是否起点和终点有共同的祖先,如果有,而且不是这个人爱喝的那种牛奶,那这个人很遗憾喝不到自己想要的牛奶,输出0

如果起点终点不在一个联通块或者起点就是他想喝的奶,那么他一定开心 输出1

#include<cstdio>
#include<iostream>
using namespace std;
int n,m,a,b,die[],ans;
char c,se[];
int find(int num)
{
if(die[num]==num)
{
return num;
}
die[num]=find(die[num]);
return die[num];
}
int main()
{
cin>>n>>m;
for(int i=;i<=n;i++)
{
die[i]=i;
cin>>se[i];
}
for(int i=;i<n;i++)
{
scanf("%d %d",&a,&b); if(se[a]==se[b])
{
die[find(a)]=find(b);//颜色相同还联通,集合起来。
}
}
for(int i=;i<=m;i++)
{
scanf("%d%d",&a,&b);
scanf(" %c",&c);//这里特别注意%c之前的空格,可以抵消掉输入时候的空格,否则c就存个空格\0
if(se[a]!=c)//如果起步就不是他喜欢的牛奶
{
if(find(a)==find(b))//而且落脚和起步在一个联通块,别想了,一路上没有什么变化,都是不想喝的牛奶
{
printf("");
}
else
{
printf("");//起步和落脚不在一个联通块,说明有不同的牛奶,一定开心!
}
}
else
{
printf("");
}
}
}

抛砖引玉,LCA入门题。一同学习,一同加油!

题目描述

Farmer John 计划建造 NN 个农场,用 N-1N−1 条道路连接,构成一棵树(也就是说,所有农场之间都互相可以到达,并且没有环)。每个农场有一头奶牛,品种为更赛牛或荷斯坦牛之一。

Farmer John 的 MM 个朋友经常前来拜访他。在朋友 ii 拜访之时,Farmer John 会与他的朋友沿着从农场 A_iAi​ 到农场 B_iBi​ 之间的唯一路径行走(可能有 A_i = B_iAi​=Bi​)。除此之外,他们还可以品尝他们经过的路径上任意一头奶牛的牛奶。由于 Farmer John 的朋友们大多数也是农场主,他们对牛奶有着极强的偏好。他的有些朋友只喝更赛牛的牛奶,其余的只喝荷斯坦牛的牛奶。任何 Farmer John 的朋友只有在他们访问时能喝到他们偏好的牛奶才会高兴。

请求出每个朋友在拜访过后是否会高兴。

输入格式

输入的第一行包含两个整数 NN 和 MM。

第二行包含一个长为 NN 的字符串。如果第 ii 个农场中的奶牛是更赛牛,则字符串中第 ii 个字符为 G,如果第 ii 个农场中的奶牛是荷斯坦牛则为 H

以下 N-1N−1 行,每行包含两个不同的整数 XX 和 YY(1 \leq X, Y \leq N1≤X,Y≤N),表示农场 XX 与 YY 之间有一条道路。

以下 MM 行,每行包含整数 A_iAi​,B_iBi​,以及一个字符 C_iCi​。A_iAi​ 和 B_iBi​ 表示朋友 ii 拜访时行走的路径的端点,C_iCi​ 是 G 或 H 之一,表示第 ii 个朋友喜欢更赛牛的牛奶或是荷斯坦牛的牛奶。

输出格式

输出一个长为 MM 的二进制字符串。如果第 ii 个朋友会感到高兴,则字符串的第 ii 个字符为 1,否则为 0

P5836 [USACO19DEC]Milk Visits S 从并查集到LCA(最近公共祖先) Tarjan算法 (初级)的更多相关文章

  1. 【并查集】【树】最近公共祖先LCA-Tarjan算法

    最近公共祖先LCA 双链BT 如果每个结点都有一个指针指向它的父结点,于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表.因此这个问题转换为两个单向链表的第一个公共结点(先分别遍历两个链表 ...

  2. 计蒜客 444 / xtuoj 1024 京东的物流路径(并查集+离线lca)或者 (点分治)

    题意:一颗树,定义一条路径的权值等于路径的边权之和,需要求这颗树所有路径中权值的最大值 思路: 考虑到路径权值与点权的最值有关,而最值的问题通常可以通过排序就行处理,于是想到先把点权排序. 容易看出如 ...

  3. 并查集及其简单应用:优化kruskal算法

    并查集是一种可以在较短的时间内进行集合的查找与合并的树形数据结构 每次合并只需将两棵树的根合并即可 通过路径压缩减小每颗树的深度可以使查找祖先的速度加快不少 代码如下: int getfather(i ...

  4. BZOJ 4668: 冷战 并查集&&暴力LCA(雾)

    利用并查集按秩合并,保存每个点合并的时间: 求时间时,就一直跳u=fa[u],并记录路径上时间的最大值,代表最后一次合并的时间 #include<cstdio> #include<i ...

  5. 【题解】[USACO19DEC]Milk Visits G

    题目戳我 \(\text{Solution:}\) 这题不要把思想局限到线段树上--这题大意就是求路径经过的值中\(x\)的出现性问题. 最开始的想法是值域线段树--看了题解发现直接\(vector\ ...

  6. P5838 [USACO19DEC]Milk Visits G

    发现是一道比较裸的树上莫队,于是就开始刚,然后发现好像是最难的一道题--(本题解用于作者加深算法理解,也欢迎各位的阅读) 题意 给你一棵树,树有点权,询问一条路径上是否有点权为 \(c\) 的点. 题 ...

  7. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  8. BZOJ-1015 StarWar星球大战 并查集+离线处理

    1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec Memory Limit: 162 MB Submit: 4105 Solved: 1826 [Submit ...

  9. 并查集(union-find sets)

    一.并查集及其优化 - 并查集:由若干不相交集合组成,是一种简单但是很好用的数据结构,拥有优越的时空复杂性,一般用于处理一些不相交集合的查询和合并问题. - 三种操作: 1.Make_Set(x) 初 ...

随机推荐

  1. cb07a_c++_迭代器和迭代器的范围

    cb07a_c++_迭代器和迭代器的范围c++primer第4版https://www.cnblogs.com/txwtech/p/12309989.html--每一种容器都有自己的迭代器--所有的迭 ...

  2. cb04a_c++_数据结构_STL_queue队列-一般用来做系统软件开发

    /*cb04a_c++_数据结构_STL_queue队列-一般用来做系统软件开发队列(只能两端数据)与堆栈(只能一端操作数据)都没有迭代器.,队列:FIFO先进先出自适应容器(容器适配器)栈适配器ST ...

  3. C# 实现定时/循环任务

    用C#实现定时/循环任务,需要使用到Quartz,在项目的NuGet包管理中可以找到并添加.一般还会伴随安装一个Log4Net,主要用它来记录在任务执行过程中遇到的问题.这边主要是讲实现定时/循环任务 ...

  4. 尚硅谷ajax视频教程2

    7.7. 尚硅谷_佟刚_Ajax_典型应用_验证用户名是否可用 整个项目的目录路径如下所示 我们首先新建立一个web工程,在webroot下面新建立一个script的文件夹,导入jquer文件 接下来 ...

  5. 微信小程序点击保存图片到本地相册——踩坑

    在微信小程序中要保存图片到本地相册,需要获取相册权限. 总之整个功能实现下来需要如下几个小程序的API:wx.getSetting,wx.authorize,wx.openSetting,wx.dow ...

  6. 【部分】ASP.NET MVC5 - 地址栏传参两种方法

    地址栏传参两种方法 1-  Home/Index/88       (后台控制器读取需要一样的参数名称) 2-  Home/Index?id1=88?id2=99    (Request三种接受方法) ...

  7. scheduler的调度规则

    对爬虫的请求进行调度管理 允许接收requests并且会调度一个request去下载,且具有去重机制 优先级和队列不会被调度器执行(调度器不管优先级的问题),用户使用字段给每个Request对象,可以 ...

  8. 一.8.django权限管理/drf权限管理

    1.什么是权限管理: .权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源 .权限管理好比如钥匙,有了钥匙就能把门打开,但是权限设置是有级别之分的,假如这个系 ...

  9. Nginx功能详细介绍(大而全)

    Nginx介绍 Nginx是C语言开发的. HTTP和反向代理Web服务器. Nginx ⼜能做什么事情(应⽤场景) Http服务器(Web服务器) 性能⾮常⾼,⾮常注重效率,能够经受⾼负载的考验. ...

  10. PDF无法复制/打印/编辑怎么办?

    PDF的内容不能复制/打印/编辑,主要有两种原因: 1.PDF文件设置了权限保护 2.PDF内容是图片 第一种,PDF被设置了权限保护 这种的特点是可以选中PDF里的文字,但无法复制 PDF格式标准内 ...