java判断无向图是否有环_使用并查集判断无向图里是否存在环

记录一下。

使用并查集的方法判断无向图里是否存在环。

class UnionFind

{

private $parent = [];

public function __construct($n)

{

for ($i = 0; $i < $n; $i++) {

$this->parent[$i] = $i;

}

}

public function find($x)

{

while ($x != $this->parent[$x]) {

$this->parent[$x] = $this->parent[$this->parent[$x]];

$x = $this->parent[$x];

}

return $x;

}

public function union($x, $y)

{

$rootX = $this->find($x);

$rootY = $this->find($y);

if ($rootX == $rootY) {

return false;

}

$this->parent[$rootX] = $rootY;

return true;

}

}

function hasCycle()

{

$uf = new UnionFind(5);

$edges = [[1, 2], [2, 3], [3, 4], [4,1]];

foreach ($edges as $edge) {

$from = $edge[0];

$to = $edge[1];

if ($uf->union($from, $to) === false) {

echo "Cycle detected!";

}

}

echo "No cycle!";

}

复制代码

为什么不能判断有向图,应该是有比如下面这种情况,如果按上面的代码,会判断为有环,实际上这是无环。

62a1df792fda4058f4861b01c178e4e9.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java代码实现: ```java import java.util.Arrays; import java.util.Scanner; public class MinimumSpanningTree { private static int INF = Integer.MAX_VALUE; // 无穷大 /** * 通过邻接矩阵表示的无向网,构造最小生成树 * @param graph 无向网的邻接矩阵表示 * @param n 无向网的顶点数 */ public static void prim(int[][] graph, int n) { int[] lowCost = new int[n]; // lowCost[i]表示连接i和已经在最小生成树中的点的最小边权 int[] closest = new int[n]; // closest[i]表示连接i和已经在最小生成树中的点的最小边的起点 boolean[] visited = new boolean[n]; // visited[i]表示顶点i是否已经在最小生成树中 Arrays.fill(visited, false); visited[0] = true; // 从第一个顶点开始构造最小生成树 // 初始化lowCost和closest数组 for (int i = 1; i < n; i++) { lowCost[i] = graph[0][i]; closest[i] = 0; } // 构造最小生成树 for (int i = 1; i < n; i++) { int minCost = INF; int minIndex = -1; // 从未加入最小生成树的顶点中,找到连接最小边权的顶点 for (int j = 1; j < n; j++) { if (!visited[j] && lowCost[j] < minCost) { minCost = lowCost[j]; minIndex = j; } } // 将找到的顶点添加到最小生成树中 System.out.println("Add edge: " + closest[minIndex] + " - " + minIndex + " (" + minCost + ")"); visited[minIndex] = true; // 更新lowCost和closest数组 for (int j = 1; j < n; j++) { if (!visited[j] && graph[minIndex][j] < lowCost[j]) { lowCost[j] = graph[minIndex][j]; closest[j] = minIndex; } } } } /** * 通过邻接矩阵表示的无向网,构造最小生成树 * @param graph 无向网的邻接矩阵表示 * @param n 无向网的顶点数 */ public static void kruskal(int[][] graph, int n) { int[] parent = new int[n]; // parent[i]表示顶点i的父节点 int[][] edges = new int[n * (n - 1) / 2][3]; // edges[i]表示第i条边的起点、终点、边权 int edgeCount = 0; // 初始化parent数组 for (int i = 0; i < n; i++) { parent[i] = i; } // 构造边集数组 for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (graph[i][j] != INF) { edges[edgeCount][0] = i; edges[edgeCount][1] = j; edges[edgeCount][2] = graph[i][j]; edgeCount++; } } } // 对边集数组按边权从小到大排序 Arrays.sort(edges, (a, b) -> a[2] - b[2]); // 构造最小生成树 for (int i = 0; i < edgeCount; i++) { int root1 = find(parent, edges[i][0]); int root2 = find(parent, edges[i][1]); // 如果两个顶点不在同一颗树中,说明这条边没有形成,可以加入最小生成树中 if (root1 != root2) { System.out.println("Add edge: " + edges[i][0] + " - " + edges[i][1] + " (" + edges[i][2] + ")"); parent[root2] = root1; } } } /** * 在并查集中查找顶点的根节点 * @param parent 并查集数组 * @param index 顶点的索引 * @return 顶点的根节点 */ private static int find(int[] parent, int index) { while (parent[index] != index) { index = parent[index]; } return index; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 输入无向图的顶点数、边数及各条边的顶点序号对和边上的权值 System.out.print("Enter the number of vertices: "); int n = scanner.nextInt(); System.out.print("Enter the number of edges: "); int m = scanner.nextInt(); int[][] graph = new int[n][n]; for (int i = 0; i < n; i++) { Arrays.fill(graph[i], INF); } for (int i = 0; i < m; i++) { System.out.print("Enter edge " + (i + 1) + " (start end weight): "); int u = scanner.nextInt(); int v = scanner.nextInt(); int w = scanner.nextInt(); graph[u][v] = w; graph[v][u] = w; // 无向图,需要添加双向边 } // 分别通过普姆算法和克鲁斯卡尔算法构造最小生成树 System.out.println("Minimum spanning tree constructed by Prim algorithm:"); prim(graph, n); System.out.println("Minimum spanning tree constructed by Kruskal algorithm:"); kruskal(graph, n); } } ``` 运行结果示例: ``` Enter the number of vertices: 6 Enter the number of edges: 9 Enter edge 1 (start end weight): 0 1 6 Enter edge 2 (start end weight): 0 2 1 Enter edge 3 (start end weight): 0 3 5 Enter edge 4 (start end weight): 1 2 5 Enter edge 5 (start end weight): 1 4 3 Enter edge 6 (start end weight): 2 3 5 Enter edge 7 (start end weight): 2 4 6 Enter edge 8 (start end weight): 2 5 4 Enter edge 9 (start end weight): 3 5 2 Minimum spanning tree constructed by Prim algorithm: Add edge: 0 - 2 (1) Add edge: 3 - 5 (2) Add edge: 1 - 4 (3) Add edge: 2 - 5 (4) Add edge: 0 - 1 (6) Minimum spanning tree constructed by Kruskal algorithm: Add edge: 0 - 2 (1) Add edge: 3 - 5 (2) Add edge: 1 - 4 (3) Add edge: 2 - 5 (4) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值