forked from sourav-122/hacktoberfest2022
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cat-and-mouse.py
121 lines (112 loc) · 3.85 KB
/
cat-and-mouse.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
112
113
114
115
116
117
118
119
120
121
# Time: O(n^3)
# Space: O(n^2)
import collections
class Solution(object):
def catMouseGame(self, graph):
"""
:type graph: List[List[int]]
:rtype: int
"""
HOLE, MOUSE_START, CAT_START = range(3)
DRAW, MOUSE, CAT = range(3)
def parents(m, c, t):
if t == CAT:
for nm in graph[m]:
yield nm, c, MOUSE^CAT^t
else:
for nc in graph[c]:
if nc != HOLE:
yield m, nc, MOUSE^CAT^t
degree = {}
ignore = set(graph[HOLE])
for m in xrange(len(graph)):
for c in xrange(len(graph)):
degree[m, c, MOUSE] = len(graph[m])
degree[m, c, CAT] = len(graph[c])-(c in ignore)
color = collections.defaultdict(int)
q = collections.deque()
for i in xrange(len(graph)):
if i == HOLE:
continue
color[HOLE, i, CAT] = MOUSE
q.append((HOLE, i, CAT, MOUSE))
for t in [MOUSE, CAT]:
color[i, i, t] = CAT
q.append((i, i, t, CAT))
while q:
i, j, t, c = q.popleft()
for ni, nj, nt in parents(i, j, t):
if color[ni, nj, nt] != DRAW:
continue
if nt == c:
color[ni, nj, nt] = c
q.append((ni, nj, nt, c))
continue
degree[ni, nj, nt] -= 1
if not degree[ni, nj, nt]:
color[ni, nj, nt] = c
q.append((ni, nj, nt, c))
return color[MOUSE_START, CAT_START, MOUSE]
# Time: O(n^3)
# Space: O(n^2)
import collections
class Solution2(object):
def catMouseGame(self, graph):
"""
:type graph: List[List[int]]
:rtype: int
"""
HOLE, MOUSE_START, CAT_START = range(3)
DRAW, MOUSE, CAT = range(3)
def parents(m, c, t):
if t == CAT:
for nm in graph[m]:
yield nm, c, MOUSE^CAT^t
else:
for nc in graph[c]:
if nc != HOLE:
yield m, nc, MOUSE^CAT^t
color = collections.defaultdict(int)
degree = {}
ignore = set(graph[HOLE])
for m in xrange(len(graph)):
for c in xrange(len(graph)):
degree[m, c, MOUSE] = len(graph[m])
degree[m, c, CAT] = len(graph[c])-(c in ignore)
q1 = collections.deque()
q2 = collections.deque()
for i in xrange(len(graph)):
if i == HOLE:
continue
color[HOLE, i, CAT] = MOUSE
q1.append((HOLE, i, CAT))
for t in [MOUSE, CAT]:
color[i, i, t] = CAT
q2.append((i, i, t))
while q1:
i, j, t = q1.popleft()
for ni, nj, nt in parents(i, j, t):
if color[ni, nj, nt] != DRAW:
continue
if t == CAT:
color[ni, nj, nt] = MOUSE
q1.append((ni, nj, nt))
continue
degree[ni, nj, nt] -= 1
if not degree[ni, nj, nt]:
color[ni, nj, nt] = MOUSE
q1.append((ni, nj, nt))
while q2:
i, j, t = q2.popleft()
for ni, nj, nt in parents(i, j, t):
if color[ni, nj, nt] != DRAW:
continue
if t == MOUSE:
color[ni, nj, nt] = CAT
q2.append((ni, nj, nt))
continue
degree[ni, nj, nt] -= 1
if not degree[ni, nj, nt]:
color[ni, nj, nt] = CAT
q2.append((ni, nj, nt))
return color[MOUSE_START, CAT_START, MOUSE]