You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
2.5 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2022_08_3_week;
import java.util.ArrayList;
// 给你一个 n 个节点的 有向图 节点编号为 0  n - 1 其中每个节点 至多 有一条出边。
// 图用一个大小为 n 下标从 0 开始的数组 edges 表示
// 节点 i 到节点 edges[i] 之间有一条有向边。如果节点 i 没有出边那么 edges[i] == -1 
// 请你返回图中的 最长 环,如果没有任何环,请返回 -1 
// 一个环指的是起点和终点是 同一个 节点的路径。
// 用强联通分量
// 测试链接 : https://leetcode.cn/problems/longest-cycle-in-a-graph/
public class Code01_LongestCycleInGraph1 {
public static int longestCycle(int[] edges) {
int n = edges.length;
ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < n; i++) {
graph.add(new ArrayList<Integer>());
}
for (int i = 0; i < n; i++) {
if (edges[i] != -1) {
graph.get(i).add(edges[i]);
}
}
StronglyConnectedComponents connectedComponents = new StronglyConnectedComponents(graph);
int m = connectedComponents.getSccn() + 1;
int[] cnt = new int[m];
int[] scc = connectedComponents.getScc();
for (int i = 0; i < n; i++) {
cnt[scc[i]]++;
}
int ans = -1;
for (int count : cnt) {
ans = Math.max(ans, count > 1 ? count : -1);
}
return ans;
}
public static class StronglyConnectedComponents {
public ArrayList<ArrayList<Integer>> nexts;
public int n;
public int stackSize;
public int cnt;
public int sccn;
public int[] stack;
public int[] dfn;
public int[] low;
public int[] scc;
public StronglyConnectedComponents(ArrayList<ArrayList<Integer>> edges) {
nexts = edges;
init();
scc();
}
private void init() {
n = nexts.size();
stackSize = 0;
cnt = 0;
sccn = 0;
stack = new int[n];
dfn = new int[n];
low = new int[n];
scc = new int[n];
}
private void scc() {
for (int i = 0; i < n; i++) {
if (dfn[i] == 0) {
tarjan(i);
}
}
}
private void tarjan(int p) {
low[p] = dfn[p] = ++cnt;
stack[stackSize++] = p;
for (int q : nexts.get(p)) {
if (dfn[q] == 0) {
tarjan(q);
}
if (scc[q] == 0) {
low[p] = Math.min(low[p], low[q]);
}
}
if (low[p] == dfn[p]) {
sccn++;
int top = 0;
do {
top = stack[--stackSize];
scc[top] = sccn;
} while (top != p);
}
}
public int[] getScc() {
return scc;
}
public int getSccn() {
return sccn;
}
}
}