Interview Questions: Directed Graphs

本文探讨了如何在有向图中寻找具有最少边的有向环,以及如何确定有向无环图(DAG)是否存在哈密顿路径。给出了从每个顶点运行BFS查找最短有向环的提示,以及通过拓扑排序寻找哈密顿路径的方法。同时,提出了线性时间算法来检查DAG和一般有向图中是否存在一个顶点可以从其他所有顶点到达,并给出相应的解决方案。
摘要由CSDN通过智能技术生成

Directed Graphs

Shortest directed cycle. Given a digraph G, design an efficient algorithm to find a directed cycle with the minimum number of edges (or report that the graph is acyclic). The running time of your algorithm should be at most proportional to V(E+V) and use space proportional to E+V, where V is the number of vertices and E is the number of edges.

Hint: run BFS from each vertex.

参考 ShortestDirectedCycle.java

Hamiltonian path in a DAG. Given a directed acyclic graph, design a linear-time algorithm to determine whether it has a Hamiltonian path (a simple path that visits every vertex), and if so, find one.

Hint: topological sort.

先计算出该图的拓扑排序序列,再判断该序列中任意两个连续的结点是否相连,若是则存在哈密顿回路,且结点顺序正是拓扑序列,若不是则不存在哈密顿回路。

import edu.princeton.cs.algs4.Digraph;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Hamiltonian {
    private List<Integer> path;
    private boolean marked[];
    private boolean hasPath;
    private Digraph G;

    public Hamiltonian(Digraph G) {
        path = new ArrayList<>();
        marked = new boolean[G.V()];
        hasPath = true;
        this.G = G;

        for (int v = 0; v < G.V(); v++) {
            if (!marked[v]) {
                dfs(v);
            }
        }
        Collections.reverse(path);

        for (int i = 0; i < path.size() - 1; i++) {
            int v = path.get(i);
            int w = path.get(i + 1);
            boolean found = false;
            for (int u : G.adj(v)) {
                if (u == w) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                hasPath = false;
                break;
            }
        }
    }

    public boolean hasPath() {
        return hasPath;
    }

    public Iterable<Integer> getPath() {
        return path;
    }

    private void dfs(int v) {
        marked[v] = true;
        for (int w : G.adj(v)) {
            if (!marked[w]) {
                dfs(w);
            }
        }
        path.add(v);
    }
}

Reachable vertex.

  • DAG: Design a linear-time algorithm to determine whether a DAG has a vertex that is reachable from every other vertex, and if so, find one.
  • Digraph: Design a linear-time algorithm to determine whether a digraph has a vertex that is reachable from every other vertex, and if so, find one.

Hint (DAG): compute the outdegree of each vertex.

Hint (digraph): compute the strong components and look at the kernel DAG (the digraph that results when you contract each strong component to a single vertex).

DAG:对于有向无环图来说,如果存在一个点X,图中其他所有点都有路径到达X,那么X的出度必为0。如果不为0,假设X能够到达点Y,而Y又有路径到达X,就构成了环,与DAG的前提矛盾。找到出度为0的点后(可能多个),在图 G G G的逆向图 G R G^R GR中判断能否从X到达所有的点(一次DFS即可),如果能说明X就是要找的点。

Digraph:对于更普遍情况的有向图,先利用Kosaraju方法标识出所有强连通分量,id最小的强连通分量中的所有点就是候选点。针对每个候选点X,在图 G G G的逆向图 G R G^R GR中判断能否从X到达所有的点(一次DFS即可),如果能说明X就是要找的点。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值