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.

162 lines
4.1 KiB

This file contains ambiguous Unicode 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_03_1_week;
// 强连通分量练习题目
// A -> B表示A认为B是红人
// A -> B -> C表示A认为B是红人B认为C是红人规定“认为”关系有传递性所以A也认为C是红人
// 给定一张有向图方式是给定M个有序对(A, B)
// (A, B)表示A认为B是红人该关系具有传递性
// 给定的有序对中可能包含(A, B)和(B, C),但不包含(A,C)
// 求被其他所有人认为是红人的总数。
// 测试链接 : http://poj.org/problem?id=2186
// 注册一下 -> 页面上点击"submit" -> 语言选择java
// 然后把如下代码粘贴进去, 把主类名改成"Main", 可以直接通过
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
public class Code03_PopularCows {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
while (in.nextToken() != StreamTokenizer.TT_EOF) {
int n = (int) in.nval;
in.nextToken();
int m = (int) in.nval;
ArrayList<ArrayList<Integer>> edges = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i <= n; i++) {
edges.add(new ArrayList<Integer>());
}
for (int i = 0; i < m; i++) {
in.nextToken();
int from = (int) in.nval;
in.nextToken();
int to = (int) in.nval;
edges.get(from).add(to);
}
StronglyConnectedComponents connectedComponents = new StronglyConnectedComponents(edges);
int sccn = connectedComponents.getSccn();
int ans = 0;
if (sccn == 1) {
ans = n;
} else {
ArrayList<ArrayList<Integer>> dag = connectedComponents.getShortGraph();
int zeroOut = 0;
int outScc = 0;
for (int i = 1; i <= sccn; i++) {
if (dag.get(i).size() == 0) {
zeroOut++;
outScc = i;
}
}
if (zeroOut > 1) {
ans = 0;
} else {
int[] scc = connectedComponents.getScc();
for (int i = 1; i <= n; i++) {
if (scc[i] == outScc) {
ans++;
}
}
}
}
out.println(ans);
out.flush();
}
}
public static class StronglyConnectedComponents {
public ArrayList<ArrayList<Integer>> nexts;
public int n;
public int[] stack;
public int stackSize;
public int[] dfn;
public int[] low;
public int cnt;
public int[] scc;
public int sccn;
// 请保证点的编号从1开始不从0开始
// 注意:
// 如果edges里有0、1、2...n这些点那么容器edges的大小为n+1
// 但是0点是弃而不用的所以1..n才是有效的点所以有效大小是n
public StronglyConnectedComponents(ArrayList<ArrayList<Integer>> edges) {
nexts = edges;
init();
scc();
}
private void init() {
n = nexts.size();
stack = new int[n];
stackSize = 0;
dfn = new int[n];
low = new int[n];
cnt = 0;
scc = new int[n];
sccn = 0;
n--;
}
private void scc() {
for (int i = 1; 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;
}
public ArrayList<ArrayList<Integer>> getShortGraph() {
ArrayList<ArrayList<Integer>> shortGraph = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i <= sccn; i++) {
shortGraph.add(new ArrayList<Integer>());
}
for (int u = 1; u <= n; u++) {
for (int v : nexts.get(u)) {
if (scc[u] != scc[v]) {
shortGraph.get(scc[u]).add(scc[v]);
}
}
}
return shortGraph;
}
}
}