对于一个图,如何求出其中的最小环(不包括一元环)?

很显然,对于一个无向图,每一条边都是一个二元环;对于有向图,可以考虑从每一个点出发,用DFS求出它到自己的距离,如果遍历了$N$个点仍未便利到自己,则该点不在环中。但是这样做的复杂度非常感人……如果没有分析错的话最坏应该是$O(n^2 m)$

可以考虑有一些优化, 对于一个点,如果它在一个环中,那么它在该环上dfs过的点一定在环中。在回溯一个点的过程中,如果搜到环,那么在搜下一个点的时候就不清空他们的标记数组。对于搜不到环的点,它的入度一定为一,如果不为一,那么删除它入边所连的入度为零的点后入度为零。所以可以预处理,删除入度为零的点和它所连的边(如果后面还有用就标记),然后再按照上述方式dfs,时间复杂度为$O(nm)$

但是对于稠密图,复杂度还是太高,甚至高过$O(n^3)$,这听起来是不是有些耳熟? 没错,Floyd。

用 $k$ 作为当前搜索点,不断求出其它点的最短路径和路经所在环长,即

   $dis[i][j] = std::max(dis[i][j], dis[i][k], dis[j][k]), ans = std::max(ans, dis[i][j]+G[k][i]+G[j][k]); // G[][] 为邻接矩阵$

时间复杂度为 $O(N^3)$

当然,在$N>1000$的稠密图中,这种方法的复杂度依然很感人。

由于连边的关系也可以看作是树中“父与子”的关系,则可以使用并查集,通过路径压缩求出在某一图中的环,若存在两个连边的点在同一并查集中,那么一定有环,环的权值为两点到祖先的权值和加1。

为什么这样是对的呢? 在一个路径已经被压缩的树中,任意两节点在图中一定相连,当某一点的父节点成为该点的子节点时,该点一定在环上。只要没有重边,那么该方法一定适用。

Floyd 代码:

int G[N][N], dis[N][N];
int main(){
for(int k = ; k <= n; k++){
for(int i=;i<=k-;i++)
for(int j=i+;j<=k-;j++)
ans = std::max(ans, dis[i][j]+G[k][i]+G[k][j]);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
dis[i][j] = std::max(dis[i][j], G[i][k]+G[k][j]);
}
//...
return ;
}

并查集代码

 int find(int x){
if(f[x] != x){
int o = f[x];
f[x] = find(f[x]);
d[x] += d[o];
}
return f[x];
}
int main(){
scanf("%d", &n);
for(int i=;i<=n;i++) f[i] = i;
for(int i=;i<=n;i++){
scanf("%d", &x);
int a = find(i), b = find(x);
if(a != b) { f[a] = b; d[i] = d[x]+; }
else min = std::min(min, d[x] + d[i] + );
}
printf("%d\n" ,min);
return ;
}

来写个裸题练练吧!https://www.luogu.org/problemnew/show/P2661

求最小环 —— 并查集 与 Floyd的更多相关文章

  1. 【bzoj2049】[Sdoi2008]Cave 洞穴勘测——线段树上bfs求可撤销并查集

    题面 2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 12030 Solved: 6024 Desc ...

  2. hdu 1213 求连通分量(并查集模板题)

    求连通分量 Sample Input2 //T5 3 //n m1 2// u v2 34 5 5 12 5 Sample Output24 # include <iostream> # ...

  3. poj 2524 求连通分量(并查集模板题)

    求连通分量 Sample Input 10 91 21 31 41 51 61 71 81 91 1010 42 34 54 85 80 0Sample Output Case 1: 1Case 2: ...

  4. tarjan求lca :并查集+dfs

    //参考博客 https://www.cnblogs.com/jsawz/p/6723221.html#include<bits/stdc++.h> using namespace std ...

  5. HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  6. TOJ3955: NKU ACM足球赛(并查集+map+细节题)

    时间限制(普通/Java):5000MS/15000MS     内存限制:65536KByte 描述 NKU ACM最近要举行足球赛,作为此次赛事的负责人,Lee要对报名人员进行分队.分队要遵循如下 ...

  7. PAT甲题题解-1021. Deepest Root (25)-dfs+并查集

    dfs求最大层数并查集求连通个数 #include <iostream> #include <cstdio> #include <algorithm> #inclu ...

  8. HDU 3461 Code Lock(并查集的应用+高速幂)

    * 65536kb,仅仅能开到1.76*10^7大小的数组. 而题目的N取到了10^7.我開始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并. 事 ...

  9. 树上莫比乌斯反演+分层图并查集——cf990G

    /* 树上莫比乌斯反演 求树上 满足 d|gcd(au,av) gcd(au,av)的对数f(d) 如何求: 建立200000层新图,即对于每个数建立一个新图 在加边时,给gcd(au,av)的约数层 ...

随机推荐

  1. AnnotationTransactionAttributeSource is only available on Java 1.5 and higher

    前言: 在eclipse中用到spring2.0的web项目,启动elipse自带的tomcat7,tomcat7报错如下: AnnotationTransactionAttributeSource ...

  2. MinHook测试分析02 (x64)

    在X64模式中,存在的问题是JMP指令和整个地址空间相比仅仅覆盖了很窄的范围.因此引入一个中继函数(Relay Function)来实现对64位Detour函数地址的跳转. 在hook的分析之前,先谈 ...

  3. 第一个HTML文档

    属性 和 值 1.作用 用来修饰元素 ex:让 p 标记的文本水平居中对齐 <p>Hello World</p> 2.语法      1.属性的声明必须位于开始标记里      ...

  4. Oracle查询和过滤重复数据

    对数据库某些意外情况,引起的重复数据,如何处理呢? ----------------查重复: select * from satisfaction_survey s and s.project_no ...

  5. JavaWeb开发流程

  6. Spring工作原理及应用

    spring原理 内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建.调用对象,Spring就是在运行时 ...

  7. 动态流程图关于jointJs的使用

    这段时间由于业务需要,需要展现动态的流程图.具体实现效果如图所示: jointJS中的线条以及框都是依赖SVG进行的二次开发.建议初学者先学习svg里相关属性,便于在阅读jointJs的API或者de ...

  8. Web开发常见的几个漏洞解决方法 (转)

    基本上,参加的安全测试(渗透测试)的网站,可能或多或少存在下面几个漏洞:SQL注入漏洞.跨站脚本攻击漏洞.登陆后台管理页面.IIS短文件/文件夹漏洞.系统敏感信息泄露. 1.测试的步骤及内容 这些安全 ...

  9. Oracle 多行变一行

    https://blog.csdn.net/rainyspring4540/article/details/50231521

  10. 2017-9-24模拟赛T1 个人卫生综合征(school.*)

    题目 每天 BBS 都要从家里经过城市中的一段路到学校刷五三.城市中一共有 n 个路口和 m 条双向道路,每条双向道路都连接着两个路口 a i .b i 且有一定的时间花费 v i .BBS家编号为 ...