当前位置:网站首页>统计无向图中无法互相到达点对数[经典建邻接表+DFS统计 -> 并查集优化][并查集手册/写的详细]
统计无向图中无法互相到达点对数[经典建邻接表+DFS统计 -> 并查集优化][并查集手册/写的详细]
2022-06-27 00:08:00 【REN_林森】
经典建邻接表+DFS统计 -> 并查集优化
前言
给定节点和边(节点对),求关于连通分量及其变种。第一想法都是根据节点和节点对(边)来建立邻接矩阵,在DFS做事。
但还有一种和连通分量紧密相关的思想,并查集,它不建立完整的图,但能做相应的事,所以运行时间短。
它将原有的图,从中选出一个节点作为根节点,所有直接/间接相连的节点都作为子节点,能解很多连通分量/连通分量变种问题。
并查集除上述优点外,我感觉它的数组hash比hashMap快,毕竟数组为JVM层面,且连续内层分配,比API快。
一、统计无向图中无法互相到达点对数


二、经典建邻接表+DFS统计 -> 并查集优化
1、经典建邻接表+DFS统计
public class CountPairs {
public long countPairs(int n, int[][] edges) {
// 加入所有节点。
for (int i = 0; i < n; i++) addNode(i);
for (int[] edge : edges) addEdge(edge[0], edge[1]);
List<Long> arr = new ArrayList<>();
for (int i = 0; i < n; i++) if (graph.containsKey(i)) arr.add(dfs(i));
//
long[] prefix = new long[arr.size()];
long sum = 0, ans = 0;
int idx = 0;
for (long i : arr) prefix[idx++] = (sum += i);
for (int i = 0; i < arr.size() - 1; i++) ans += arr.get(i) * (prefix[arr.size() - 1] - prefix[i]);
return ans;
}
private long dfs(int n) {
long rs = 1;
Set<Integer> next = graph.get(n);
if (next == null) return rs;
graph.remove(n);
for (Integer i : next) {
if (graph.containsKey(i)) rs += dfs(i);
}
return rs;
}
private void addEdge(int a, int b) {
addNode(a);
addNode(b);
graph.get(a).add(b);
graph.get(b).add(a);
}
private void addNode(int b) {
if (!graph.containsKey(b)) graph.put(b, new HashSet<>());
}
Map<Integer, Set<Integer>> graph = new HashMap<>();
}
2、并查集优化
// 练习哈并查集,它是关于连通分量的利器。
class CountPairs2 {
public long countPairs(int n, int[][] edges) {
// 并查集标准第一步:初始化。
int[] father = new int[n];
Arrays.fill(father, -1);
// 并查集标准第二步:union
cnt = n;// 这里想统计连通分量个数,方便等会统计每个连通分量的节点数,可以用到数组,而不是可扩容的list.| 也可直接list
for (int[] edge : edges) union(father, edge[0], edge[1]);
// 非特定逻辑,具体需求具体写。
// 统计每个连通分量节点数。
int[] arr = new int[cnt];
cnt = 0;
for (int f : father) if (f < 0) arr[cnt++] = -f;
// 非特定逻辑,具体需求具体写。
// 得到不同连通分量的节点数,利用前缀和,空间换时间。
long[] prefix = new long[arr.length];
long sum = 0;
cnt = 0;
for (int a : arr) prefix[cnt++] = (sum += a);
// 得到结果
long ans = 0;
for (int i = 0; i < arr.length - 1; i++) ans += arr[i] * (prefix[prefix.length - 1] - prefix[i]);
return ans;
}
int cnt = 0;// 连通分量个数。
private void union(int[] father, int m, int n) {
// 并查集标准第三步:findFather
int r1 = findFather(father, m);
int r2 = findFather(father, n);
// 非同一逻辑,根据实际情况来写。
if (r1 != r2) {
// 合并两者,就将一个作为根,得到其整个树的节点数,这里负数表示。
father[r1] += father[r2];
// 并把另一个作为子树,并把其根节点修改。
father[r2] = r1;
// 可选操作,当用list时,则不必。
--cnt;
}
}
private int findFather(int[] father, int r) {
// 一路返回根,并把根作为路径上每个节点的根.
// 体现在 if (father[r] != r) father[r] = findFather(father, father[r]); return father[r];这将把有深度的树平铺起来。
// 但是这里不行,因为根节点的值不是等于其下标,是负数,需要统计节点个数。
// 这里需要一改传统做法,要灵活变通。
// 若该节点是根
if (father[r] < 0) return r;
return father[r] = findFather(father, father[r]);
}
}
总结
1)经典邻接表建立 + 在dfs遍历(图操作的基础)做各自事。
2)并查集将图的形状改掉,但不影响解题,则它降低的运行时间就变成了优点。
3)并查集除上述优点外,我感觉它的数组hash比hashMap快,毕竟数组为JVM层面,且连续内层分配,比API快。
4)并查集经典三步,每步都可因具体需求,而灵活变通写法。具体三步为:初始化数组father[size]{}(数组hash非常nice)、union(int[],int,int)联结两节点、findFather(int[],int)寻找根节点。
参考文献
边栏推荐
- Is it reliable to speculate in stocks by mobile phone? Is it safe to open an account and speculate in stocks online
- 【Mysql】时间字段默认设置为当前时间
- Cve-2022-30190 follina office rce analysis [attached with customized word template POC]
- MATLAB data type - character type
- Can I open an account for stock trading on my mobile phone? Is it safe to open an account for stock trading on the Internet
- 目前哪个证券公司炒股开户是最好最安全的?
- 高清滑环生产过程当中的质量如何把控
- Big guys talk about the experience sharing of the operation of the cutting-edge mindspore open source community. Come up with a small notebook!
- From bitmap to bloom filter, C # implementation
- [microservices] understanding microservices
猜你喜欢

Lwip之ARP模块实现

Oracle database basics concepts

消息队列简介

Lorsque le transformateur rencontre l'équation différentielle partielle

Oracle 數據庫基本知識概念

com. fasterxml. jackson. databind. exc.MismatchedInputException: Expected array or string. at [Source:x

Hit the point! The largest model training collection!

直播回顾 | 子芽&CCF TF:云原生场景下软件供应链风险治理技术浅谈

Is there anyone who doesn't know the three cores of concurrent programming?
![[vscade] preview MD file](/img/b8/0413eaade0a7da9ddb5494b093665c.png)
[vscade] preview MD file
随机推荐
复杂数据没头绪?
Encapsulate servlet unified processing request
Kubernetes visual interface dashboard
技术干货|什么是大模型?超大模型?Foundation Model?
Freescale 单片机概述
test
Amway! How to provide high-quality issue? That's what Xueba wrote!
Pinpoint attackers with burp
PHP code audit series (I) basis: methods, ideas and processes
Leetcode skimming 4 Find the median of two positive arrays
Can't write to avoid killing and can easily go online CS through defender
find_ Detailed use guide of CIRC
Understanding of "the eigenvectors corresponding to different eigenvalues cannot be orthogonalized"
2022年地理信息系统与遥感专业就业前景与升学高校排名选择
[micro service]nacos
全網最全的混合精度訓練原理
在线上买养老年金险正规安全吗?有没有保单?
冲刺强基计划数学物理专题二
1+1<2 ?! HESIC论文解读
Network in network (dolls)