Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Leetcode 2360. Longest Cycle in a Graph

Woodyiiiiiii opened this issue · comments

这是求无向图中最短环问题。2608. Shortest Cycle in a Graph

有模版:遍历所有结点,对结点BFS,记录每个经过的结点的距离,这样就能计算环的长度。判断是否有环是通过父子结点和结点距离来综合判断。复杂度是O(nm)。

Tips: 存储边的信息可以用Map<Integer, Set>或者List[] g,通常来说,边稀疏的图用Map,边密集的图用List[],比如这道题,改用List[]后从Beats 5%到72%,有点像领接矩阵。

class Solution {
    List<Integer>[] g;
    int[] dist;

    public int findShortestCycle(int n, int[][] edges) {
        dist = new int[n];
        g = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            g[i] = new ArrayList<>();
        }
        for (int[] edge : edges) {
            g[edge[0]].add(edge[1]);
            g[edge[1]].add(edge[0]);
        }
        int res = Integer.MAX_VALUE;
        for (int i = 0; i < n; ++i) {
            res = Math.min(res, bfs(i));
        }
        return res == Integer.MAX_VALUE ? -1 : res;
    }
    
    private int bfs(int i) {
        Arrays.fill(dist, -1);
        Queue<int[]> q = new ArrayDeque<>();
        q.offer(new int[]{i, -1});
        dist[i] = 0;
        int res = Integer.MAX_VALUE;
        while (!q.isEmpty()) {
            int[] cur = q.poll();
            for (int next : g[cur[0]]) {
                if (dist[next] == -1) {
                    dist[next] = dist[cur[0]] + 1;
                    q.offer(new int[]{next, cur[0]});
                } else if (next != cur[1]) {
                    res = Math.min(res, dist[cur[0]] + dist[next] + 1);
                }
            }
        }
        return res;
    }
}

下面是有向图的环计算。同样可以DFS或者BFS。2360. Longest Cycle in a Graph,参考资料:Graphs | All Algorithms | Theroy And Implementation

类似拓扑排序2603. Collect Coins in a Tree。先剔除环之外的结点,判断有无环之后,再对环进行长度计算。

bfs:

class Solution {
    int[] inDegree;
    int[] edges;
    int[] dist;
    int n;

    public int longestCycle(int[] edges) {
        this.n = edges.length;
        this.edges = edges;
        this.dist = new int[n];
        Arrays.fill(dist, -1);
        this.inDegree = new int[n];
        for (int i = 0; i < n; i++) {
            if (edges[i] != -1) {
                inDegree[edges[i]]++;
            }
        }
        
        int max = 0, count = 0;
        Queue<Integer> queue = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }
        while (!queue.isEmpty()) {
            int cur = queue.poll();
            ++count;
            dist[cur] = 0;
            if (edges[cur] != -1) {
                inDegree[edges[cur]]--;
                if (inDegree[edges[cur]] == 0) {
                    queue.offer(edges[cur]);
                }
            }
        }
        if (count == n) {
            return -1;
        }

        for (int i = 0; i < n; ++i) {
            if (dist[i] == -1) {
                max = Math.max(max, bfs(i));
            }
        }
        return max;
    }
    
    private int bfs(int start) {
        int max = 0;
        Queue<Integer> queue = new ArrayDeque<>();
        queue.offer(start);
        dist[start] = 0;
        while (!queue.isEmpty()) {
            int cur = queue.poll();
            if (edges[cur] != -1) {
                if (dist[edges[cur]] == -1) {
                    dist[edges[cur]] = dist[cur] + 1;
                    queue.offer(edges[cur]);
                } else {
                    max = Math.max(max, dist[cur] + 1 + dist[edges[cur]]);
                }
            }
        }
        return max;
    }
}