по рёбрам против стрелочек
На самом деле нет никакой разницы между направлениями: стрелки можно обратить. Или хранить для каждой вершины не только список потомков, но и список родителей.
Т.е. останутся только кратчайшие пути от каждой вершины до корня.
Смысл как раз в обратном: от корня к каждой вершине идёт по стрелочке, надо из них выкинуть лишние. Равно как от каждой вершины к макушке идёт по стрелочке, часть из них — так же лишние.
Получается три вложенных цикла.
Набросал пока тестовый вариант с массивами (в основной программе у меня динамические структуры данных):
import java.util.*;
public class Study_Hasse_Diagram {
private static Scanner scanner = new Scanner(System.in);
private static int[][] graph;
private static boolean[][] flags;
public static void main(String[] args) {
int k, l, m, n, nodesNumber, childrenNumber, grandchildrenNumber;
boolean[] nodesFlags;
boolean displayFlag;
System.out.println("Input data:");
nodesNumber = scanner.nextInt();
graph = new int[nodesNumber][];
flags = new boolean[nodesNumber][];
for (k = 0; nodesNumber > k; ++k) {
childrenNumber = scanner.nextInt();
graph[k] = new int[childrenNumber];
flags[k] = new boolean [childrenNumber];
for (l = 0; childrenNumber > l; ++l) {
graph[k][l] = scanner.nextInt();
}
}
scanner.close();
for (k = 0; nodesNumber > k; ++k) {
childrenNumber = graph[k].length;
nodesFlags = new boolean[nodesNumber];
for (l = 0; childrenNumber > l; ++l) {
m = graph[k][l];
grandchildrenNumber = graph[m].length;
for (n = 0; grandchildrenNumber > n; ++n) {
nodesFlags[graph[m][n]] = true;
}
}
for (l = 0; childrenNumber > l; ++l) {
if (nodesFlags[graph[k][l]]) {
flags[k][l] = true;
}
}
}
System.out.println("\nFull graph:");
for (k = 0; nodesNumber > k; ++k) {
System.out.print(String.format("%d", k));
childrenNumber = graph[k].length;
displayFlag = false;
for (l = 0; childrenNumber > l; ++l) {
if (displayFlag) {
System.out.print(String.format(", %d", graph[k][l]));
} else {
displayFlag = true;
System.out.print(String.format(" -> %d", graph[k][l]));
}
}
System.out.println('.');
}
System.out.println("\nHasse graph:");
for (k = 0; nodesNumber > k; ++k) {
System.out.print(String.format("%d", k));
childrenNumber = graph[k].length;
displayFlag = false;
for (l = 0; childrenNumber > l; ++l) {
if (!flags[k][l]) {
if (displayFlag) {
System.out.print(String.format(", %d", graph[k][l]));
} else {
displayFlag = true;
System.out.print(String.format(" -> %d", graph[k][l]));
}
}
}
System.out.println('.');
}
}
}
Примеры работы:
(Раз)
Input data:
15
14 1 2 3 4 5 6 7 8 9 10 11 12 13 14
2 10 11
2 10 12
7 1 7 10 11 12 13 14
2 10 13
7 2 6 10 11 12 13 14
2 10 12
2 10 11
2 10 13
7 4 8 10 11 12 13 14
0
1 10
1 10
1 10
4 10 11 12 13
Full graph:
0 -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.
1 -> 10, 11.
2 -> 10, 12.
3 -> 1, 7, 10, 11, 12, 13, 14.
4 -> 10, 13.
5 -> 2, 6, 10, 11, 12, 13, 14.
6 -> 10, 12.
7 -> 10, 11.
8 -> 10, 13.
9 -> 4, 8, 10, 11, 12, 13, 14.
10.
11 -> 10.
12 -> 10.
13 -> 10.
14 -> 10, 11, 12, 13.
Hasse graph:
0 -> 3, 5, 9.
1 -> 11.
2 -> 12.
3 -> 1, 7, 14.
4 -> 13.
5 -> 2, 6, 14.
6 -> 12.
7 -> 11.
8 -> 13.
9 -> 4, 8, 14.
10.
11 -> 10.
12 -> 10.
13 -> 10.
14 -> 11, 12, 13.
(Два)
Input data:
18
17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
2 12 13
2 12 14
7 1 8 12 13 14 15 16
2 12 15
2 12 15
9 2 4 5 7 12 13 14 15 16
2 12 14
2 12 13
6 12 13 14 15 16 17
6 12 13 14 15 16 17
14 1 2 3 4 5 6 7 8 12 13 14 15 16 17
0
1 12
1 12
1 12
4 12 13 14 15
5 12 13 14 15 16
Full graph:
0 -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17.
1 -> 12, 13.
2 -> 12, 14.
3 -> 1, 8, 12, 13, 14, 15, 16.
4 -> 12, 15.
5 -> 12, 15.
6 -> 2, 4, 5, 7, 12, 13, 14, 15, 16.
7 -> 12, 14.
8 -> 12, 13.
9 -> 12, 13, 14, 15, 16, 17.
10 -> 12, 13, 14, 15, 16, 17.
11 -> 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15, 16, 17.
12.
13 -> 12.
14 -> 12.
15 -> 12.
16 -> 12, 13, 14, 15.
17 -> 12, 13, 14, 15, 16.
Hasse graph:
0 -> 9, 10, 11.
1 -> 13.
2 -> 14.
3 -> 1, 8, 16.
4 -> 15.
5 -> 15.
6 -> 2, 4, 5, 7, 16.
7 -> 14.
8 -> 13.
9 -> 17.
10 -> 17.
11 -> 3, 6, 17.
12.
13 -> 12.
14 -> 12.
15 -> 12.
16 -> 13, 14, 15.
17 -> 16.
(Три)
Input data:
40
39 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
3 29 30 31
2 29 32
11 1 19 21 23 29 30 31 32 33 34 35
3 29 33 36
3 29 34 37
3 29 32 38
3 29 32 39
3 29 34 39
3 29 32 36
3 29 30 38
7 2 29 30 32 33 34 35
3 29 33 39
3 29 34 36
3 29 32 37
3 29 33 37
11 4 9 13 25 29 30 32 33 34 35 36
3 29 30 37
3 29 34 38
3 29 31 32
11 5 14 15 17 29 30 32 33 34 35 37
3 29 31 33
11 7 8 12 27 29 30 32 33 34 35 39
3 29 31 34
3 29 33 38
3 29 30 36
11 6 10 18 24 29 30 32 33 34 35 38
3 29 30 39
13 2 6 7 9 14 19 29 31 32 36 37 38 39
0
1 29
1 29
1 29
1 29
1 29
5 29 30 32 33 34
1 29
1 29
1 29
1 29
Full graph:
0 -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39.
1 -> 29, 30, 31.
2 -> 29, 32.
3 -> 1, 19, 21, 23, 29, 30, 31, 32, 33, 34, 35.
4 -> 29, 33, 36.
5 -> 29, 34, 37.
6 -> 29, 32, 38.
7 -> 29, 32, 39.
8 -> 29, 34, 39.
9 -> 29, 32, 36.
10 -> 29, 30, 38.
11 -> 2, 29, 30, 32, 33, 34, 35.
12 -> 29, 33, 39.
13 -> 29, 34, 36.
14 -> 29, 32, 37.
15 -> 29, 33, 37.
16 -> 4, 9, 13, 25, 29, 30, 32, 33, 34, 35, 36.
17 -> 29, 30, 37.
18 -> 29, 34, 38.
19 -> 29, 31, 32.
20 -> 5, 14, 15, 17, 29, 30, 32, 33, 34, 35, 37.
21 -> 29, 31, 33.
22 -> 7, 8, 12, 27, 29, 30, 32, 33, 34, 35, 39.
23 -> 29, 31, 34.
24 -> 29, 33, 38.
25 -> 29, 30, 36.
26 -> 6, 10, 18, 24, 29, 30, 32, 33, 34, 35, 38.
27 -> 29, 30, 39.
28 -> 2, 6, 7, 9, 14, 19, 29, 31, 32, 36, 37, 38, 39.
29.
30 -> 29.
31 -> 29.
32 -> 29.
33 -> 29.
34 -> 29.
35 -> 29, 30, 32, 33, 34.
36 -> 29.
37 -> 29.
38 -> 29.
39 -> 29.
Hasse graph:
0 -> 3, 11, 16, 20, 22, 26, 28.
1 -> 30, 31.
2 -> 32.
3 -> 1, 19, 21, 23, 35.
4 -> 33, 36.
5 -> 34, 37.
6 -> 32, 38.
7 -> 32, 39.
8 -> 34, 39.
9 -> 32, 36.
10 -> 30, 38.
11 -> 2, 35.
12 -> 33, 39.
13 -> 34, 36.
14 -> 32, 37.
15 -> 33, 37.
16 -> 4, 9, 13, 25, 35.
17 -> 30, 37.
18 -> 34, 38.
19 -> 31, 32.
20 -> 5, 14, 15, 17, 35.
21 -> 31, 33.
22 -> 7, 8, 12, 27, 35.
23 -> 31, 34.
24 -> 33, 38.
25 -> 30, 36.
26 -> 6, 10, 18, 24, 35.
27 -> 30, 39.
28 -> 2, 6, 7, 9, 14, 19.
29.
30 -> 29.
31 -> 29.
32 -> 29.
33 -> 29.
34 -> 29.
35 -> 30, 32, 33, 34.
36 -> 29.
37 -> 29.
38 -> 29.
39 -> 29.
Работать работает, но вопрос о более рациональном алгоритме пока открыт.
-- 09.04.2020, 08:37 --А нельзя ли из вершины пустить обратную волну по рёбрам против стрелочек?
Вообще, идея интересная. Можно начать с корня, идти по стрелочкам и каждому следующему поколению присваивать на единицу большую величину. Тогда искомыми рёбрами диаграммы Хассе будут стрелочки, соединяющие вершины с разницей присвоенных величин в единицу. Однако, у такого подхода есть подвох в случае, если две ветви графа содержат разное число поколений, например: