Her değiştirme işleminde (doğrudan ebeveyn-çocuk değiştirmeleri hariç), uzun vadede hangisinin buna değdiğini belirlemeyi önemsiz hale getiren yeni ata-torun ilişkileri eklersiniz. Bu nedenle, basit bir açgözlü algoritma genel durumda başarısız olacaktır. Ancak, kaba kuvvet yaklaşımı yaparsanız, en küçük grafiği belirleyebilirsiniz:
Python-ish (test edilmedi):
def play((V,E),F,sequence=[]):
"""
(V,E) -- a dag.
V -- a set of vertices.
E -- a set of directed-edge-tuples.
F -- a function that takes a vertex, returns an integer.
sequence -- the sequence of moved taken so far; starts with/defaults to
an empty list, will contain tuples of the form (x,y)
where x is removed and replaced with y.
Returns the best recursively found solution.
"""
#find all the integer values in the graph, remember which
# values correspond to what vertices. Of the form {integer => {vertices}}.
n2v = {}
for x in V:
n = F(x)
#for each integer, make sure you have a set to put the vertices in.
if n not in n2v:
n2v[n] = set()
#for each integer, add the vertex to the equivalent set.
n2v[n].add(v)
#record the best sequence/solution. You start with the current sequence,
# and see if you can obtain anything better.
best_solution = list(sequence)
#Now you will try to combine a single pair of vertices, obtain a new
# graph and then recursively play the game again from that graph.
#for each integer and equivalent set of vertices,
for n,vset in n2v.iteritems():
#pick a pair of vertices
for x in vset:
for y in vset:
#no point if they are the same.
if x == y:
continue
#If there is a path from x => y or y => x, then you will be
# introducing a cycle, breaking a rule. So in that case, disregard
# this pair.
#However, the exception is when one is a direct child of the other;
# in that case you can safely combine the vertices.
if pathtest((V,E),x,y) and (x,y) not in E and (x,y) not in E:
continue
#combine the vertices (function is defined below), discard x,
# replace it with y, obtain the new graph, (V',E').
Vp,Ep = combine_vertex((V,E),x,y))
#record the sequence for this move.
sequencep = list(sequence) + [(x,y)]
#recurse and play the game from this new graph.
solution = play(Vp,Ep,F,sequencep)
#if the returned solution is better than the current best,
if len(solution) > len(best_solution):
#record the new best solution
best_solution = solution
#return the best recorded solution
return best_solution
def combine_vertex((V0,E0),x,y):
"""
(V0,E0) -- an initial digraph.
V0 -- a set of vertices.
E0 -- a set of directed-edge-tuples.
x -- vertex to discard.
y -- vertex to replace it with.
returns a new digraph replacing all relationships to and from x to relate
to y instead, and removing x from the graph entirely.
"""
#the final vertex set will have everything except x
V = set(V0)
V.discard(x)
#now you construct the edge set.
E = set()
#for every edge,
for (u0,v0) in E0:
#recreate the edge in the new graph, but replace any occurence
# of x.
u,v = u0,v0
#if x is in the edge: replace it
if u == x:
u = y
if v == x:
v == y
#sometimes u=v=y and can now be pointing to itself, don't add that
# edge
if u == v:
continue
#add the new/replaced edge into the edge-set.
E.add( (u,v) )
return (V,E)
Gerçekten zor bir sorun olup olmadığından emin değilim, ancak bazı grafikler ile manuel olarak oynamak, çok birleştirici görünüyor. Zor bir şeyin bu probleme indirgenebileceğini veya daha iyi çalışma süresine sahip bir algoritma olup olmadığını merak ediyorum.