[JAVA] find the number of points that may be in the second position of topological sorting (Pro20210924) (topological sorting)


N people are holding a one-on-one competition. Everyone's strength is certain, different from each other and will not change. The outcome of the game is always determined by strength. Because we haven't finished all the competitions, we can't accurately see who is the first and who is the second.

For example, suppose you know the results of the following part of the game. Contestants are numbered from 1 to N. the person at the starting point of the arrow loses to the person at the end of the arrow. (win ← lose)

[figure 1]

In [figure 1], there are 4 people who may become the first, 2, 3, 5 and 8. Because the first place has not been determined, four people may become the second place. If someone loses to only one of 2, 3, 5 and 8, he may also be the second, but there is no such situation in the above figure. Although 4 only lost to No. 6, but 6 lost to 2 and 8, it can't be the first place. Therefore, it can be known that 4 can only be below the third place. Look at the following.

[figure 2]

In this case, it can be determined that 8 is the first. So 8 can't be the second. Losing only to 8's 1, 2 and 6 is likely to be second.

Input the results of the competition, write a program and calculate the number of people who may be second.


  1. The number of people N is an integer between 2 and 100000.
  2. The number of matches M is an integer between 0 and 200000.
  3. One cannot compete with oneself.

The first line gives the number of test cases T. Then T test cases are given. The first line of each test case gives the number of people N and the number of games M. In the next M lines, each line gives the numbers a and B of 2 people representing the result of a game, separated by spaces. A wins B.

Output the answers of each test case in order with standard output. For each test case, first output "#x" (x is the test case number, starting from 1 without quotation marks), then output a space, and then output the number of people who may be the second.

[input / output example]
8 7
8 1
8 6
2 1
2 6
6 4
2 7
3 7
8 10
8 1
8 6
8 2
8 4
2 5
2 7
2 3
3 7
4 3
6 4
4 3
1 2
3 4
1 2
#1 4
#2 3
#3 4


Make complaints about water
After the original graph is reversed, the number of points where the topological sorting may be in the second position can be calculated (there is no need to calculate the topological sorting result, only the concept of penetration is considered).

  1. After the original drawing is reversed, calculate the number P of points with a penetration of 0. If P ==1, the point will be the first and P will be reset to 0; (if P > 1, these points may be the second, and P is reserved);
  2. Among the reachable points of points with 0 penetration, the number Q of points with 1 penetration (if the penetration is greater than 1, it cannot be the second);
  3. P + Q is the desired.

Note: duplicate edges will be given in Case to reconstruct the proposed Set. (the List.Contains() method is a circular judgment, which is too inefficient. It is not recommended to use it.)


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

public class Main {
	static int T, N, M, ASW, IN[];
	static Set<Integer>[] DATA;

	public static void main(String[] args) throws Exception {
		System.setIn(new FileInputStream("D:\\SW\\TestCase\\sample_input_20210924.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		T = Integer.parseInt(br.readLine());

		for (int t = 1; t <= T; t++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			ASW = N;

			IN = new int[N + 1];
			DATA = new HashSet[N + 1];
			for (int n = 1; n <= N; n++)
				DATA[n] = new HashSet<Integer>();

			for (int a, b, m = 0; m < M; m++) {
				st = new StringTokenizer(br.readLine());
				a = Integer.parseInt(st.nextToken());
				b = Integer.parseInt(st.nextToken());

				if (DATA[a].add(b) && ++IN[b] == 1) ASW--;

			if (ASW == 1) ASW = 0;

			for (int n = 1; n <= N; n++) {
				if (IN[n] > 0) continue;

				for (int next : DATA[n])
					if (IN[next] == 1) ASW++;

			System.out.println(t + " " + ASW);

Tags: Java Algorithm

Posted on Wed, 29 Sep 2021 00:02:31 -0400 by kristy7