import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) throws IOException {
for (int i = 0; i <= 100000; i++) adj.add(new LinkedList<>());
in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int T = nextInt();
for (int tc = 1; tc <= T; tc++) {
readCase();
work();
System.out.println("#" + tc + " " + ans);
}
}
static void work() {
//找出入度为0的点,从这样的点开始拓扑排序(遍历)
for (int i = 1; i <= N; i++) {
if (inDep[i] == 0) {
topQue.add(i);
cnt[i] = 1;
}
}
long maxV = 0; //最大深度值
//拓扑排序(遍历)
while (!topQue.isEmpty()) {
int fm = topQue.poll();
while (!adj.get(fm).isEmpty()) {
int to = adj.get(fm).poll();
if (cnt[to] < cnt[fm] + 1) {
cnt[to] = cnt[fm] + 1;
p[to] = fm;
maxV = Math.max(cnt[to], maxV);
} else if (cnt[to] == cnt[fm] + 1) {
p[to] = Math.max(p[to], fm);
}
if (--inDep[to] == 0) topQue.add(to);
}
}
//找出最大深度点
for (int i = 1; i <= N; i++) {
if (cnt[i] == maxV) topQue.add(i);
}
//通过每个点的前驱点p[],计算加和,求最大ans
while (!topQue.isEmpty()) {
int nx = topQue.poll();
long sum = 0;
while (nx != 0) {
sum += nx * cnt[nx];
nx = p[nx];
}
ans = Math.max(sum, ans);
}
Arrays.fill(inDep, 0, N + 1, 0);
Arrays.fill(cnt, 0, N + 1, 0);
}
static void readCase() throws IOException {
N = nextInt();
M = nextInt();
for (int i = 0; i < M; i++) {
int a = nextInt();
int b = nextInt();
adj.get(b).add(a);
inDep[a]++;
}
}
static int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
static StreamTokenizer in;
static int N, M;
static long ans;
static final int[] inDep = new int[100002];
static final long[] cnt = new long[100002];
static final int[] p = new int[100002];
static final ArrayList<LinkedList<Integer>> adj = new ArrayList<>();
static final LinkedList<Integer> topQue = new LinkedList<>();
}
2021-09-10(拓扑排序)
猜你喜欢
转载自blog.csdn.net/awp0011/article/details/120229310
今日推荐
周排行