P 算法与 K 算法

作者:Grey

原文地址:

博客园:P 算法与 K 算法

CSDN:P 算法与 K 算法

说明

P 算法和 K 算法主要用来解决最小生成树问题,即:不破坏连通性删掉某些边,使得整体的权重最小。

测评链接:牛客-最小生成树

K 算法

K 算法使用的核心数据结构是并查集,然后将边权值排序。

1)总是从权值最小的边开始考虑,依次考察权值依次变大的边

2)当前的边要么进入最小生成树的集合,要么丢弃

3)如果当前的边进入最小生成树的集合中不会形成环,就要当前边

4)如果当前的边进入最小生成树的集合中会形成环,就不要当前边

5)考察完所有边之后,最小生成树的集合也得到了

边存在小根堆里面,保证每次弹出的都是权重最小的值

点存在并查集中,每次加入一个边,就把两个边的点 union

完整代码如下

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();int[][] graph = new int[m][3];for (int i = 0; i < m; i++) {// fromgraph[i][0] = in.nextInt();// tograph[i][1] = in.nextInt();// weightgraph[i][2] = in.nextInt();}System.out.println(k(graph, n));in.close();}// k算法生成最小生成树public static int k(int[][] graph, int n) {UnionFind uf = new UnionFind(n);Arrays.sort(graph, Comparator.comparingInt(o -> o[2]));int ans = 0;for (int[] edge : graph) {if (!uf.same(edge[0], edge[1])) {uf.union(edge[0], edge[1]);ans += edge[2];}}return ans;}public static class UnionFind {private final int[] parent;private final int[] size;private final int[] help;public UnionFind(int n) {parent = new int[n + 1];size = new int[n + 1];help = new int[n + 1];for (int i = 1; i < n; i++) {parent[i] = i;size[i] = 1;}}public boolean same(int a, int b) {return find(a) == find(b);}private int find(int a) {int index = 0;while (a != parent[a]) {help[index++] = a;a = parent[a];}index--;while (index > 0) {parent[help[index--]] = a;}return a;}public void union(int a, int b) {int f1 = find(a);int f2 = find(b);if (f1 != f2) {int size1 = size[f1];int size2 = size[f2];if (size1 > size2) {parent[f2] = f1;size[f2] = 0;size[f1] = size1 + size2;} else {parent[f1] = f2;size[f1] = 0;size[f2] = size1 + size2;}}}}
}

P 算法

1)可以从任意节点出发来寻找最小生成树

2)某个点加入到被选取的点中后,解锁这个点出发的所有新的边

3)在所有解锁的边中选最小的边,然后看看这个边会不会形成环

4)如果会,不要当前边,继续考察剩下解锁的边中最小的边,重复3)

5)如果不会,要当前边,将该边的指向点加入到被选取的点中,重复2)

6)当所有点都被选取,最小生成树就得到了

完整代码如下

import java.util.*;public class Main {public static Set<Edge> P(Graph graph) {// 解锁的边进入小根堆PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(Comparator.comparingInt(o -> o.weight));// 哪些点被解锁出来了HashSet<Node> nodeSet = new HashSet<>();Set<Edge> result = new HashSet<>(); // 依次挑选的的边在result里for (Node node : graph.nodes.values()) { // 随便挑了一个点// node 是开始点if (!nodeSet.contains(node)) {nodeSet.add(node);for (Edge edge : node.edges) { // 由一个点,解锁所有相连的边priorityQueue.add(edge);}while (!priorityQueue.isEmpty()) {Edge edge = priorityQueue.poll(); // 弹出解锁的边中,最小的边Node toNode = edge.to; // 可能的一个新的点if (!nodeSet.contains(toNode)) { // 不含有的时候,就是新的点nodeSet.add(toNode);result.add(edge);for (Edge nextEdge : toNode.edges) {priorityQueue.add(nextEdge);}}}}// 如果有森林,就不能break,如果没有森林,就可以break//break;}return result;}public static class Graph {public HashMap<Integer, Node> nodes;public HashSet<Edge> edges;public Graph(int n) {nodes = new HashMap<>();edges = new HashSet<>(n);}}public static class Node {public int value;public int in;public int out;public ArrayList<Node> nexts;public ArrayList<Edge> edges;public Node(int value) {this.value = value;in = 0;out = 0;nexts = new ArrayList<>();edges = new ArrayList<>();}}public static class Edge {public int weight;public Node from;public Node to;public Edge(int weight, Node from, Node to) {this.weight = weight;this.from = from;this.to = to;}}public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();Graph graph = new Graph(n);for (int i = 0; i < m; i++) {int from = in.nextInt();int to = in.nextInt();int weight = in.nextInt();if (!graph.nodes.containsKey(from)) {graph.nodes.put(from, new Node(from));}if (!graph.nodes.containsKey(to)) {graph.nodes.put(to, new Node(to));}Node fromNode = graph.nodes.get(from);Node toNode = graph.nodes.get(to);Edge fromToEdge = new Edge(weight, fromNode, toNode);Edge toFromEdge = new Edge(weight, toNode, fromNode);fromNode.nexts.add(toNode);fromNode.out++;fromNode.in++;toNode.out++;toNode.in++;fromNode.edges.add(fromToEdge);toNode.edges.add(toFromEdge);graph.edges.add(fromToEdge);graph.edges.add(toFromEdge);}Set<Edge> result = P(graph);int sum = 0;for (Edge edge : result) {sum += edge.weight;}System.out.println(sum);in.close();}
}

更多

算法和数据结构笔记

参考资料

算法和数据结构体系班-左程云

P 算法与 K 算法相关推荐

  1. Kruskal算法与Prim算法

    (话说这么些算法的名字嗯... Kruskal算法:(下文它就暂时叫k算法吧 k算法是一种应用贪心思想及并查集,在图中查找最小生成树的算法. (最小生成树:若一个无向图内任意两个顶点联通切图为一棵树, ...

  2. k近邻算法之 k值的选择

    k近邻算法之 k值的选择 举例说明: K值过小:  [过拟合] ​ 容易受到异常点的影响   [如:美人鱼本身就是喜剧片,假如统计的时候记为动作片,则对预测值的影响太大] k值过大:  [欠拟合] ​ ...

  3. Kmeans++、Mini-Batch Kmeans、Bisecting Kmeans、K中心点(K-Medoids)算法、K众数聚类、核K均值聚类

    Kmeans++.Mini-Batch Kmeans.Bisecting Kmeans.K中心点(K-Medoids)算法.K众数聚类.核K均值聚类 目录 Kmeans++.Mini-Batch Km ...

  4. KNN 最近邻算法(K近邻)

    机器学习教程 正在计划编写中,欢迎大家加微信 sinbam 提供意见.建议.纠错.催更. KNN(K-Nearest Neighbor)是机器学习入门级的分类算法,也是最为简单的算法.它实现将距离近的 ...

  5. 机器学习里如何确定K-Means算法的K值?

    [问题] Kmeans算法中,K值所决定的是在该聚类算法中,所要分配聚类的簇的多少.Kmeans算法对初始值是比较敏感的,对于同样的k值,选取的点不同,会影响算法的聚类效果和迭代的次数. [解决方案] ...

  6. leetcode算法题--K站中转内最便宜的航班★

    原题链接:https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/ 1.递归(超时) 代码: int findCheapest ...

  7. 【算法】快速选择算法 ( 数组中找第 K 大元素 )

    算法 系列博客 [算法]刷题范围建议 和 代码规范 [算法]复杂度理论 ( 时间复杂度 ) [字符串]最长回文子串 ( 蛮力算法 ) [字符串]最长回文子串 ( 中心线枚举算法 ) [字符串]最长回文 ...

  8. 算法杂货铺——k均值聚类(K-means)

    算法杂货铺--k均值聚类(K-means) 2010-09-20 20:05 by T2噬菌体, 57998 阅读, 48 评论, 收藏, 编辑 4.1.摘要 在前面的文章中,介绍了三种常见的分类算法 ...

  9. Top K算法问题的实现

    前奏     在上一篇文章,程序员面试题狂想曲:第三章.寻找最小的k个数中,后来为了论证类似快速排序中partition的方法在最坏情况下,能在O(N)的时间复杂度内找到最小的k个数,而前前后后upd ...

最新文章

  1. 通信中的频谱效率与能量效率
  2. Angular ngTemplateOutlet
  3. js 自定义 $ 选择器
  4. day03_01 Python历史、32bit和64bit系统的区别
  5. Qt_QTableWidget 详解 最全用法 网格线样式 最后一列自拉伸
  6. UnityHub下载缓存位置
  7. 制造行业主数据治理项目实施心得
  8. JS实现图片的懒加载
  9. 牛客网高级项目课总结
  10. 纯c语言----学生成绩管理系统
  11. Java实现支付宝网页支付
  12. 关于VSCode安装 python 语法检测器插件 pylint 配置(Mac)
  13. JavaScript-Tool:Moment.js
  14. SDE:Stochastic Differential Equation 简述
  15. JS-JavaScript_简介及基本使用
  16. Unity 接入百度AI - 动物识别
  17. Android开发之控制手机振动(Vibrator的使用)
  18. 希尔伯特黄变换(Hilbert-Huang)原理、HHT求时频谱、边际谱,及MATLAB(2018rb)实现
  19. x64枚举DPC定时器
  20. BZOJ3827[Poi2014] Around the world

热门文章

  1. 74HC02或非门仿真示例
  2. Go语言安装和配置SDK
  3. 免费好用的录屏软件OBS-Studio
  4. Android作业批改系统(后台管理+前台app)
  5. 余承东:华为技术走在产业前列,别人想超越很难;理想销量夺冠后,员工不满年终奖打折;黑客窃取GitHub代码签名证书|极客头条
  6. A survey on challenges and progresses in blockchain technologies区块链综述
  7. 用Matlab作函数的图像
  8. Typora Syntax
  9. [编程题]漂流船问题
  10. 打印机经常没反应的一个解决办法