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;
}
}