1. 程式人生 > 其它 >拓撲排序+dfs+內向基環樹

拓撲排序+dfs+內向基環樹

每個連通塊必定有且僅有一個環,且由於每個點的出度均為 11,這樣的有向圖又叫做內向基環樹

題解連結

class Solution {
    public int maximumInvitations(int[] favorite) {
        int n = favorite.length;
        Map<Integer, Integer> graph = new HashMap<>();  // 正圖:i -> favorite[i]
        Map<Integer, List<Integer>> reGraph = new
HashMap<>(); // 反圖 int[] inDegree = new int[n]; // 記錄入度資訊 for (int i = 0; i < n; i++) { graph.put(i, favorite[i]); reGraph.putIfAbsent(favorite[i], new ArrayList<>()); reGraph.get(favorite[i]).add(i); inDegree[favorite[i]]
++; } // 拓撲排序進行剪枝處理 Queue<Integer> que = new LinkedList<>(); for (int i = 0; i < n; i++) { if (inDegree[i] == 0) que.offer(i); } while (!que.isEmpty()) { int curr = que.poll(); inDegree[graph.get(curr)]--;
if (inDegree[graph.get(curr)] == 0) { que.offer(graph.get(curr)); } } // 根據處理後的入度資訊來查詢基環 List<List<Integer>> baseCircles = findBaseCircle(favorite, inDegree); boolean[] vis = new boolean[n]; for (int i = 0; i < n; i++) { // 入度大於0,表示在環上; 基環長度為2的時候,不能走這些在環上的點 vis[i] = inDegree[i] > 0; } int sumLength = 0; int max = Integer.MIN_VALUE; for (List<Integer> circle: baseCircles) { if (circle.size() > 2) { max = Math.max(circle.size(), max); } else { // 基環長度為2的時候,沿著反圖查詢最長路徑 sumLength += findLeftOrRightLength(circle.get(0), reGraph, vis) + findLeftOrRightLength(circle.get(1), reGraph, vis); } } return Math.max(max, sumLength); } // 遞迴尋找最長的路徑 private int findLeftOrRightLength(int curr, Map<Integer, List<Integer>> reGraph, boolean[] vis) { List<Integer> nextList = reGraph.get(curr); if (nextList == null) return 1; int max = 0; for (int next: nextList) { if (vis[next]) continue; max = Math.max(max, findLeftOrRightLength(next, reGraph, vis)); } return max + 1; } private List<List<Integer>> findBaseCircle(int[] favorite, int[] inDegree) { int n = favorite.length; List<List<Integer>> baseCircles = new ArrayList<List<Integer>>(); boolean[] vis = new boolean[n]; for (int i = 0; i < n; i++) { // 入度為零 表示已經不在環上,標記為已訪問即可 vis[i] = inDegree[i] == 0; } for (int i = 0; i < n; i++) { if (vis[i]) continue; int next = i; List<Integer> baseCircle = new ArrayList<>(); while (!vis[next]) { baseCircle.add(next); vis[next] = true; next = favorite[next]; } baseCircles.add(baseCircle); } return baseCircles; } }

作者:Ryanjie

出處:http://www.cnblogs.com/ryanjan/

本文版權歸作者和部落格園所有,歡迎轉載。轉載請在留言板處留言給我,且在文章標明原文連結,謝謝!

如果您覺得本篇博文對您有所收穫,覺得我還算用心,請點選右下角的 [推薦],謝謝!