1
+ from collections import defaultdict , deque , Counter
2
+ # d = deque()
3
+ # d.append(5)
4
+ # x = d.popleft()
5
+ import re
6
+ # m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
7
+ # # or re.search
8
+ # >>> m.group(0) # The entire match
9
+ # 'Isaac Newton'
10
+ # >>> m.group(1) # The first parenthesized subgroup.
11
+ # 'Isaac'
12
+ # >>> m.group(2) # The second parenthesized subgroup.
13
+ # 'Newton'
14
+ # >>> m.group(1, 2) # Multiple arguments give us a tuple.
15
+ # ('Isaac', 'Newton')
16
+ from heapq import heappush , heappop
17
+ # >>> heap = []
18
+ # >>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
19
+ # >>> for item in data:
20
+ # ... heappush(heap, item)
21
+ # heap[0] is the smallest item
22
+ import string
23
+ # string.ascii_lowercase == 'abcde...'
24
+ # string.ascii_uppercase == 'ABCDE...'
25
+ from functools import lru_cache
26
+ # @lru_cache(maxsize=None)
27
+
28
+ import sys
29
+
30
+ sys .setrecursionlimit (100000 )
31
+
32
+ def get_ints (s ):
33
+ return list (map (int , re .findall (r"-?\d+" , s ))) # copied from mcpower from mserrano on betaveros' recommendation
34
+ dirs = [(0 ,1 ), (1 ,0 ), (0 ,- 1 ), (- 1 ,0 )]
35
+ directions = 'RDLU'
36
+ octs = [(0 ,1 ),(1 ,1 ),(1 ,0 ),(1 ,- 1 ),(0 ,- 1 ),(- 1 ,- 1 ),(- 1 ,0 ),(- 1 ,1 )]
37
+ def is_grid_valid (n ,m , r ,c ,):
38
+ return (0 <= r < n ) and (0 <= c < m )
39
+ def sign_of (x ):
40
+ if x == 0 :
41
+ return 0
42
+ return x / abs (x )
43
+
44
+ bitops = dict ()
45
+ for i in range (60 ):
46
+ bitops [i ] = (1 << i )
47
+ if True :
48
+ T = 30
49
+ ans = 0
50
+ inps = []
51
+ while True :
52
+ try :
53
+ inps .append (input ())
54
+ except EOFError :
55
+ break
56
+ edges = defaultdict (list )
57
+ flows = dict ()
58
+ v_to_i = dict ()
59
+ c = 0
60
+ for inp in inps :
61
+ s = inp .split ()
62
+ v = s [1 ]
63
+ x = get_ints (inp )[0 ]
64
+ es = inp .split ('valve' )[1 ]
65
+ if es [0 ] == 's' :
66
+ es = es [1 :]
67
+ es = es .split (',' )
68
+ es = [e .strip () for e in es ]
69
+ edges [v ] = es
70
+ flows [v ] = x
71
+ if x != 0 :
72
+ v_to_i [v ] = c
73
+ c += 1
74
+ T = 26
75
+ # dp = dict()
76
+ # dp['AA'][(1<<len(v_to_i))-1] = (0,0)
77
+ # for i in range(T):
78
+ # newdp = defaultdict(lambda: defaultdict(int))
79
+ # for u in dp:
80
+ # for bitset in dp[u]:
81
+ # best_so_far = dp[u][bitset]
82
+ # can_turn_on = False
83
+ # if flows[u]!=0 and ((1<<v_to_i[u]) & bitset) != 0:
84
+ # can_turn_on = True
85
+ # bit = (1<<v_to_i[u])
86
+ # if can_turn_on:
87
+ # newdp[u][bitset ^ bit] =
88
+ next_step = defaultdict (dict )
89
+ for u in flows :
90
+ backtrace = dict ()
91
+ q = deque ([u ])
92
+ while len (q ) > 0 :
93
+ v = q .popleft ()
94
+ for w in edges [v ]:
95
+ if w in backtrace :
96
+ continue
97
+ backtrace [w ] = v
98
+ q .append (w )
99
+ for v in v_to_i :
100
+ w = v
101
+ while w in backtrace and backtrace [w ] != u :
102
+ w = backtrace [w ]
103
+ next_step [u ][v ] = w
104
+
105
+
106
+ @lru_cache (maxsize = None )
107
+ def get_flow (bitset ):
108
+ flow = 0
109
+ for v , i in v_to_i .items ():
110
+ bit = bitops [i ]
111
+ if (bit & bitset ) == 0 :
112
+ flow += flows [v ]
113
+ return flow
114
+ came_from = dict ()
115
+
116
+ counter = 0
117
+ seen = set ()
118
+ def dead_end (vw ,t ,bitset ,dests ):
119
+ # for tt in range(0,t+1):
120
+ # if (vw,tt,bitset,dests) in seen:
121
+ # return True
122
+ return False
123
+ @lru_cache (maxsize = None )
124
+ def dfs (vw ,t ,bitset , dests ):
125
+ if dead_end (vw ,t ,bitset ,dests ):
126
+ return 0
127
+ seen .add ((vw ,t ,bitset ,dests ))
128
+ global counter
129
+ v ,w = vw
130
+ vdest , wdest = dests
131
+ flow = get_flow (bitset )
132
+ if t == T :
133
+ counter += 1
134
+ if counter % 100000 == 0 :
135
+ print (counter )
136
+ return 0
137
+ if bitset == 0 :
138
+ print ('got em all' )
139
+ return dfs (vw , t + 1 , bitset , dests ) + flow
140
+ # if flow < 50 and t > 8:
141
+ # print('dull')
142
+ # return 0
143
+ best = 0
144
+ for a ,b in [(0 ,1 ), (1 ,0 ), (1 ,1 ), (0 ,0 )]:
145
+ bitset2 = bitset
146
+ if a :
147
+ can_turn_on = False
148
+ if flows [v ]!= 0 and ((bitops [v_to_i [v ]]) & bitset ) != 0 :
149
+ can_turn_on = True
150
+ bit = (1 << v_to_i [v ])
151
+ bitset2 ^= bit
152
+ if not can_turn_on :
153
+ continue
154
+ if b :
155
+ can_turn_on = False
156
+ if flows [w ]!= 0 and ((bitops [v_to_i [w ]]) & bitset ) != 0 :
157
+ can_turn_on = True
158
+ bit = (1 << v_to_i [w ])
159
+ bitset2 ^= bit
160
+ if not can_turn_on :
161
+ continue
162
+
163
+ if a :
164
+ vvvs = [(v , None )]
165
+ else :
166
+ if vdest is not None :
167
+ destinations = [vdest ]
168
+ else :
169
+ destinations = next_step [v ]
170
+ vvvs = []
171
+ for destination in destinations :
172
+ if ((bitops [v_to_i [destination ]])& bitset2 )!= 0 :
173
+ vvvs .append ((next_step [v ][destination ], destination ))
174
+ if len (vvvs )== 0 :
175
+ vvvs = [(v , None )]
176
+ if b :
177
+ wwws = [(w , None )]
178
+ else :
179
+ if wdest is not None :
180
+ destinations = [wdest ]
181
+ else :
182
+ destinations = next_step [w ]
183
+ wwws = []
184
+ for destination in destinations :
185
+ if ((bitops [v_to_i [destination ]])& bitset2 )!= 0 :
186
+ wwws .append ((next_step [w ][destination ], destination ))
187
+ if len (wwws )== 0 :
188
+ wwws = [(v , None )]
189
+ # cfv,cfw = None,None
190
+ # if (vw,t,bitset) in came_from:
191
+ # cfv, cfw = came_from[(vw,t,bitset)]
192
+ for vvv ,vvvdest in vvvs :
193
+ for www ,wwwdest in wwws :
194
+ # if vvv==cfv or www==cfw:
195
+ # continue
196
+ vx , wx = vvv ,www
197
+ # if vx > wx:
198
+ # vx,wx = wx,vx
199
+ # came_from[(vx,wx),t+1,bitset2] = vw
200
+ xx = dfs ((vx ,wx ),t + 1 ,bitset2 , (vvvdest , wwwdest )) + flow
201
+ # xx = dfs(v,t+1,bitset) + flow
202
+ best = max (best , xx )
203
+ return best
204
+
205
+ ans = dfs (('AA' , 'AA' ), 0 , (bitops [len (v_to_i )])- 1 , (None ,None ))
206
+ print (ans )
207
+ # start = 'AA'
208
+ # v = start
209
+ # i = 0
210
+ # cur_flow = 0
211
+ # while i < T:
212
+ # print(cur_flow)
213
+ # ans += cur_flow
214
+ # time_remaining = T-i
215
+ # backtrace = dict()
216
+ # q = deque([(v,0)])
217
+ # seen = set()
218
+ # best = 0
219
+ # argbest = None
220
+ # while len(q) > 0:
221
+ # print(q)
222
+ # ex, t = q.popleft()
223
+ # time = (time_remaining - t - 1)
224
+ # score = time * flows[ex]
225
+ # if score > best:
226
+ # best = score
227
+ # argbest = ex
228
+ # for u in edges[ex]:
229
+ # if u in seen:
230
+ # continue
231
+ # q.append((u,t+1))
232
+ # seen.add(u)
233
+ # backtrace[u] = ex
234
+ # if argbest == v:
235
+ # cur_flow += flows[v]
236
+ # flows[v] = 0
237
+ # else:
238
+ # while argbest in backtrace and backtrace[argbest] != v:
239
+ # argbest = backtrace[argbest]
240
+ # if argbest is not None:
241
+ # v = argbest
242
+ # i += 1
243
+
244
+ # print(ans)
245
+ else :
246
+ pass
0 commit comments