-
Notifications
You must be signed in to change notification settings - Fork 2
/
P.py
115 lines (88 loc) · 2.99 KB
/
P.py
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import sys
sys.setrecursionlimit(100000000)
from collections import defaultdict
def read_vals():
return [int(x) for x in input().strip().split()]
while True:
N,=read_vals()
if N == 0:
break
start, target = input().split()
G = defaultdict(list)
for _ in range(N):
toks = input().split()
toks = [sys.intern(t) for t in toks]
node = toks[0]
toks = toks[2:-1]
cost = len(list(filter(lambda x: x[0] == '"', toks)))
ch = list(filter(lambda x: x[0] != '"', toks))
goal = target in toks
G[node].append((cost,ch,goal))
#print("G", G)
mincosts = {n:-2 for n in G}
gcosts = {n:-2 for n in G}
visited = set()#start]
def visit(n,visited_,mincosts_):
##print("visit", n, "visited=", visited)
if n in mincosts_ and mincosts_[n] != -2:
return mincosts_[n]
if n in visited_:
return 10000000000
visited_.add(n)
mcost = 10000000000
for cost, ch,goal in G[n]:
for child in ch:
cost += visit(child,visited_, mincosts_)
mcost = min(mcost, cost)
mincosts_[n] = mcost
visited_.remove(n)
return mcost
visit(start, visited,mincosts)
visited = set()#start]
#print("mincosts:", mincosts)
def visit2(n):
#print(" " * len(visited), "visit2",n)
if gcosts[n] != -2:
#print(" " * len(visited), "cached", gcosts[n])
return gcosts[n]
if n in visited:
#print(" " * len(visited), "loop")
return 10000000000
visited.add(n)
mcost = 10000000000
for cost, ch,goal in G[n]:
if goal:
#temp = cost + sum(mincosts[child] for child in ch)
tempvisited = set()
tempmincost = {}
for child in ch:
cost += visit(child, tempvisited, tempmincost)
#print(" " * len(visited), "reach goal w ch", ch, "cost", temp)
mcost = min(mcost, cost)
else:
temp1 = [visit2(c) for c in ch]
temp2 = [mincosts[c] for c in ch]
total = cost + sum(temp2)
for i1 in range(len(ch)):
rcost = total - temp2[i1] + temp1[i1]
mcost = min(mcost, rcost)
# for i1,child in enumerate(ch):
# rcost = cost
# for i2,c2 in enumerate(ch):
# if i1 == i2:
# rcost += visit2(c2)
# else:
# rcost += mincosts[c2]
# #print(" " * len(visited), "try", child,"rcost", rcost)
# mcost = min(mcost, rcost)
gcosts[n] = mcost
visited.remove(n)
return mcost
x=visit2(start)
#print("gcosts:", gcosts)
if x >= 1e9:
print(-1)
else:
print(x)
#print()
input()