Давай шаг за шагом.
1. Напиши программу, которая читает FO представление, и сохраняет информацию о ребрах так, чтобы можно было удобно бегать по ребрам, исходящим из данной вершины. Программа должна содержать процедуру PrintEdges(i: longint), печатающую ребра, входящие в вершину i, и ребра, исходящие из нее.
Итак, на вход программа получает FO представление, на выходе - что-то типа такого:
Код
Вершина 1
Исходящие ребра: 1-2 1-3 1-6
Входящие ребра: 4-1
Вершина 2
Исходящие ребра: 2-3
Входящие ребра: 1-2
Вершина 3
Исходящие ребра: 3-5 3-6
Входящие ребра: 1-3 2-3
...
2. Теперь напиши программу, которая выдаст список *всех* возможных поддеревьев данного графа.
Делаем это так.
Упорядочим все ребра (пронумеруем).
Сначала построим список всех поддеревьев, содержащих 0 ребер. Т.е. просто берем все вершины, каждую из них обзываем поддеревом.
Теперь построим все поддеревья, использующие только первое ребро. Для этого надо попытаться к каждому из его концов прикрепить одно из уже построеных поддеревьев.
Теперь построим все поддеревья, использующие только первых два ребра (но не обязательно оба). Для этого надо попытаться к каждому из концов второго ребра прикрепить одно из уже построеных поддеревьев.
Теперь построим все поддеревья, использующие только первых три ребра (но не обязательно каждое). Для этого надо попытаться к каждому из концов третьего ребра прикрепить одно из уже построеных поддеревьев.
И так далее.
Давай на твоем примере.
FO = 4240020
Пронумеруем ребра (как угодно)
Ребро 1: 1->2
Ребро 2: 3->2
Ребро 3: 1->4
Поддеревья будем описывать так: [(список_вершин), (список_ребер)]
Поддеревья, содержащие 0 ребер: {[(1), ()], [(2), ()], [(3), ()], [(4), ()]}
Теперь попробуем использовать ребро 1, т.е. ребро 1->2. Нам надо из уже построенного списка поддеревьев {[(1), ()], [(2), ()], [(3), ()], [(4), ()]} присоединить что-то к 1, а что-то к 2. В данном случае единственный результат - это [(1, 2), (1->2)].
Получили список подграфов, в котором используется только первое ребро:
{[(1), ()], [(2), ()], [(3), ()], [(4), ()], [(1, 2), (1->2)]}
Следующее ребро: 3->2. Пробуем присоединить. К тройке можно присоединить только [(3), ()], а к двойке - либо [(2), ()], либо [(1, 2), (1->2)]. Получаем еще два новых поддерева: [(2, 3), (3->2)] и [(1, 2, 3), (1->2, 3->2)]. Общий список:
{[(1), ()], [(2), ()], [(3), ()], [(4), ()], [(1, 2), (1->2)], [(2, 3), (3->2)], [(1, 2, 3), (1->2, 3->2)]}
И последнее ребро: 1->4. К четверке можно присоединить только [(4), ()], а к единице уже кучу всего: [(1), ()], [(1, 2), (1->2)], [(1, 2, 3), (1->2, 3->2)]. Получаем новых 3 поддерева. Общий список выглядит так:
{[(1), ()], [(2), ()], [(3), ()], [(4), ()], [(1, 2), (1->2)], [(2, 3), (3->2)], [(1, 2, 3), (1->2, 3->2)], [(1, 4), (1->4)], [(1, 2, 4), (1->2, 1->4)], [(1, 2, 3, 4), (1->2, 3->2, 1->4)]}
Вот мы и построили все связные подграфы. В общем случае, пытаясь использовать новое ребро x->y, мы бежим по списку уже построенных поддеревьев, и выбираем содержащие вершину x; пусть нашлось n вариантов. Потом бежим еще раз, и выбираем содержащие вершину y; пусть нашлось m вариантов. Тогда для каждого из n вариантов пробуем каждый из m вариантов, и получаем nm вариантов использования нового ребра.
Что не понятно, спрашивай.