Here is another approach. As in the answer by DYZ, let anc
denote the ancestors and desc
denote the descendants of the chosen node. Let nodes
= anc
union desc
union {chosen_node}
. Iterate over edges (i, j)
of the original graph, and delete an edge if either of the following holds:
i
or j
are not in the set nodes
.
i
is in anc
and j
is in desc
.
A node x not in nodes
cannot be on any path containing chosen_node
, or else x
would have to be an ancestor, a descendant, or chosen_node
itself (condition 1). If (i, j)
is a node from an ancestor i
to descendant j
, it cannot be on any path containing chosen_node
because of the acyclic assumption (condition 2).
Every remaining edge is on some path containing the chosen_node
. I believe you can prove it by induction on min(distance(i, chosen_node), distance(j, chosen_node))
.
def remove_edges(G, node=0):
desc = nx.descendants(G, node)
anc = nx.ancestors(G, node)
nodes = anc.union(desc).union({node})
Q = nx.DiGraph()
for i, j in G.edges:
# remove edges with either source or target not in nodes
if (i not in nodes) or (j not in nodes):
continue
# remove edges immediately connecting ancestors to descendants
if (i in anc) and (j in desc):
continue
Q.add_edge(i,j)
return Q