图论:并查集求最小环

概念:

图、路、环

一个有向图由G=(N,A)表示,其中N表示节点集,A表示边集边(i,j)为一有序对,i为出发节点,j为终止节点。在无向图中(i,j)与(j,i)一致。

是由节点及其对应的边依次相连构成。

是出发节点和终止节点相同的路。

如果一条路不含重复边和重复节点,就被称做简单路,出发节点和终止节点相同的简单路就被称为简单环。

对于有向图而言 可以使用拓扑排序的方式找出图中的环

引入例题:

P2661 信息传递

题目描述

有 nnn 个同学(编号为 111 到 nnn )正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为 iii 的同学的信息传递对象是编号为 TiT_iTi 的同学。

游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息, 但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自 己的生日时,游戏结束。请问该游戏一共可以进行几轮?

输入格式

共2行。

第1行包含1个正整数 n ,表示 n 个人。

第2行包含 n 个用空格隔开的正整数 T1,T2,⋯⋯ ,Tn,其中第 iii 个整数 Ti 表示编号为 i 的同学的信息传递对象是编号为 Ti 的同学, Ti≤n 且 Ti≠i。

输出格式

1个整数,表示游戏一共可以进行多少轮。

输入输出样例

输入 #1

5
2 4 2 3 1

输出 #1

3

说明/提示

样例1解释

游戏的流程如图所示。当进行完第3 轮游戏后, 4号玩家会听到 2 号玩家告诉他自己的生日,所以答案为 3。当然,第 3轮游戏后,2号玩家、3 号玩家都能从自己的消息来源得知自己的生日,同样符合游戏结束的条件。

对于 30%的数据, n≤200;

对于 60%的数据, n≤2500;

对于100%的数据, n≤200000。

解析:

首先,通过题目可能想到的是暴力建立set判重。

本题难点在于,怎么看出他是一并查集的题,讲真,题目的描述,一轮一轮的感觉与并查集风牛马牛不相及,但是非要联系的话,首先想到是:图,那把图画出来:

画完我们得知,要求的游戏轮数,就抽象在这个环里,简言之就是:存在环的话,生日就可以传到自己耳朵里,传递次数为环的大小。

来源题解:

anyway

把每个同学看成一个点,信息的传递就是在他们之间连有向边,游戏轮数就是求最小环。

图论求最小环,我在里面看到了并查集。

假如说信息由A传递给B,那么就连一条由A指向B的边,同时更新A的父节点**,A到它的父节点的路径长也就是B到它的父节点的路径长+1。**

这样我们就建立好了一个图,之后信息传递的所有环节都按照这些路径。游戏结束的轮数,也就是这个图里最小环的长度。

如果有两个点祖先节点相同,那么就可以构成一个环,长度为两个点到祖先节点长度之和+1。

和下面的并查集有点不一样的。

代码:

(简略注释在代码中给出,*下方有详细解释)


import java.util.Scanner;
/** P2661 信息传递     并查集求最小环*/
public class P2661 {static Scanner sc= new Scanner(System.in);static int n=sc.nextInt();static int f[]=new int[200005];//这是节点的父节点数组static int d[]=new int[200005];//这是到父节点的距离static int min=n;//设置一个最小环数(初始值设为最大)public static void main(String[] args) {for (int i = 1; i <= n; i++) {f[i]=i;//初始化,让自己当自己的”嗲“;}for (int i = 1; i <=n ; i++) {int to=sc.nextInt();check(i,to);//------------------------------------*1*}System.out.println(min);}private static void check(int i, int to) {// 经典check函数int x=getfa(i);int y=getfa(to);//找爹,也就是“让boss之间谈话”if(x!=y){f[x]=y;//让boss会话,并认右为王d[i]=d[to]+1;//-----------------------------------*2*}else{min=Math.min(min, d[i]+d[to]+1);//----------------*3*//长度为两个点到祖先节点长度之和+1。}}private static int getfa(int x) {//经典找爹函数if(f[x]!=x){int origin=f[x];f[x]=getfa(f[x]);//小细节:不是getfa(x)是getfa(f[x]);d[x]+=d[origin];//-------------------------------*4*//更新路径长(原来连在父节点上)。} return f[x];}
}

难点&精彩点:

  1. 首先就是并查集的知识:建议先学几个并查集的例子在做这个题,否则不懂,强推《啊哈!算法》p200页的知识,记住“擒贼先擒王的口诀”和“以左为王”的口诀

  2. *1*这里我认为理解起来有难度,(呵呵,也许是我太笨,反正就这个循环,我受题面“轮数”影响,想了好久才想出来)这里其实和题目的轮数无关,以后也不要记轮数了,总之就是要把这几个点一个个输入,边输入边判断已有的点集合,是否存在环,以及是否存在最小值。

  3. *2*这里的d[i]=d[to]+1;要点有二,一是方括号里必须是判断值,而不是其父值。也就是说”找祖宗“只是为了判断是否在一点集内,而对父节点的距离数组进行记录时是对i,to,操作的。而加一操作见下图:

  4. *3*,这个地方,,怎么说,代码作者很强,应该是分析出的规律:长度为两个点到祖先节点长度之和+1。

  5. *4*这地方,的确很难想,这个地方和路径压缩有关,很巧妙,我试了试,只能把他放在递归后侧回溯的过程中,然后相当于“拾级而上,不断累加”太难想了对我···哈哈感觉遇到了瓶颈。(菜鸡的瓶颈未免也太低啦哈哈)

小结:

很好的考察了并查集,递归,图论的部分知识。尤其是在两个经典并查集函数中,其中关于路径的记录很考察人的水平。

,这个地方和路径压缩有关,很巧妙,我试了试,只能把他放在递归后侧回溯的过程中,然后相当于“拾级而上,不断累加”太难想了对我···哈哈感觉遇到了瓶颈。(菜鸡的瓶颈未免也太低啦哈哈)

小结:

很好的考察了并查集,递归,图论的部分知识。尤其是在两个经典并查集函数中,其中关于路径的记录很考察人的水平。

图论:并查集求最小环相关推荐

  1. 信息传递(带权并查集求最小环

    P2661 [NOIP2015 提高组] 信息传递 题意: nnn 个同学玩信息传递,第 iii 个同学只会将信息传递给同学 TiT_iTi​,游戏开始时每个人只知道自己的生日,一轮游戏同学 iii ...

  2. 图论500题 ---- 并查集求路径上最大值最小不超过K的点对数 HDU Portal

    题目链接 题目大意: 就给你一个图,qqq次询问,问你这个图上有多少对点之间的所以路径上的最大值的最小值不超过kkk? 解题思路: 首先我们知道这本质上就是求两个点联通的路径上的最大值最小是多少? 那 ...

  3. 图论 + 并查集 ----最小生成树重构图 + 可撤销并查集 + set启发式合并 时间线上的离线求解 D. Graph and Queries

    解题思路 题目大意: 就是给你一个无向图,每个点都有一个权值,和qqq次询问 每次询问有两种操作 1 x:就询问从x点出发,能访问到的最大权值是多少,并把最大权值那个点的权值设置为0 2 x:就是删除 ...

  4. 牛客小白月赛25 C-白魔法师 ( 图论 + 并查集 )

    题目链接 解题报告: 思路:如果将一个黑色点染成白色,那么将得到一个白色连通块,这个连通块由和这个黑色点连结的所有白色连通块组成. 如果将一个白色点染成白色,那么不会有任何变化. 所以我们可以先并查集 ...

  5. 并查集求欧拉回路/通路

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1116 题意:给你一些英文单词,判断所有单词能不能连成一串,类似成语接龙.但是如果有多个重复的单词时,也必须 ...

  6. hdu 1856 并查集 求最大的子树含有元素的个数

    这道题数据有点大, 我再次 被 cin>> he  cin<<out 多次超时, 改成 scanf 和 printf  后一次ac . 欲哭无泪啊! 完全是 并查集 ,模板 , ...

  7. 图论500题 ---- (枚举+并查集)求图上路径权值差值最小 HDU find the most comfortable road

    题目链接 解题思路: 对于两个点的路径假设我们把边按照边权进行排序那么,再把边依次加入图中判断两点的联通性,那么这个边就是两个点联通的最小的最大值,但是最大的最小值怎么找? 因为我们是把边权按照从小到 ...

  8. 2013吉林通化邀请赛 1004 D-City 并查集求连通分支数

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4496 将题目要查询的数倒过来求,先加一条边,保存cc(连通分支数)  然后再加一条边.... 当合并两 ...

  9. java并查集找朋友圈_并查集求朋友圈最大人数

    #include #include using namespace std ; int findRoot( int set[ ], int s ) { if (s == set[s]) return ...

最新文章

  1. 3-2.6==0.4
  2. Hasor JDBC 的难关,嵌套事务处理思路
  3. Shell——read读取控制台输入和函数
  4. AI研发工程师成长指南
  5. 【C语言】递归详解汉诺塔问题
  6. 数据挖掘常用的基本技术,主要有哪些?
  7. 计算机桌面鼠标锁定了怎么办,笔记本鼠标锁住怎么办
  8. VS应用程序无法正常启动0xc0150002
  9. 使用PS蒙版功能去水印以及Word中的图片合并功能合并公司Logo图片
  10. webpack中loader和plugin的区别
  11. 阿里java类注释模板_向IDE导入阿里编码规约格式化模板和注释模板
  12. 免费智能机器人聊天API
  13. python|教你用代码画“社会人”
  14. connect holder is null问题记录
  15. 今宵多珍重(珍藏绝版精选)铃声 今宵多珍重(珍藏绝版精选)手机...
  16. shell 编程--shell的扩展功能(字符串切割与掐头去尾)、通配符、设置语言字符集
  17. matlab 零速检测,一种基于车辆零速检测的惯性导航误差修正方法与流程
  18. 操作操作操作操作操作操作
  19. 添加百度统计,有利于网站SEO,百度终于发声了
  20. 考研复试资格审查政审是什么?有什么用?

热门文章

  1. 利用Java Calendar类打印日历
  2. react native 和 小米 MIUI
  3. Java基础知识11——数组
  4. 我的奇思妙想机器人消防员_我的奇思妙想机器人作文600字
  5. 噗浪(Plurk)创办人 -- 云惟彬:低薪陷阱 廉价的薪水 等待的成本
  6. 二叉搜索树的JAVA实现-201805
  7. CSS渐变颜色和浏览器前缀、opacity透明度以及设置多个背景图片写法
  8. MSP430之BR0、BR1计算
  9. 虚拟机u盾怎么使用_虚拟机用U盾支付安全吗
  10. 手机和电脑的文件传输利器(FE文件管理器)