@@ -82,3 +82,106 @@ class Solution {
82
82
return result;
83
83
}
84
84
};
85
+
86
+ // Time: O(n^3)
87
+ // Space: O(n^2)
88
+ class Solution2 {
89
+ private:
90
+ template <typename A, typename B, typename C>
91
+ struct TupleHash {
92
+ size_t operator ()(const tuple<A, B, C>& p) const {
93
+ size_t seed = 0 ;
94
+ A a; B b; C c;
95
+ tie (a, b, c) = p;
96
+ seed ^= std::hash<A>{}(a) + 0x9e3779b9 + (seed<<6 ) + (seed>>2 );
97
+ seed ^= std::hash<B>{}(b) + 0x9e3779b9 + (seed<<6 ) + (seed>>2 );
98
+ seed ^= std::hash<C>{}(c) + 0x9e3779b9 + (seed<<6 ) + (seed>>2 );
99
+ return seed;
100
+ }
101
+ };
102
+ using Lookup = unordered_map<tuple<int , int , int >, int , TupleHash<int , int , int >>;
103
+
104
+ enum Location {HOLE, MOUSE_START, CAT_START};
105
+ enum Result {DRAW, MOUSE, CAT};
106
+
107
+ public:
108
+ int catMouseGame (vector<vector<int >>& graph) {
109
+ Lookup degree;
110
+ unordered_set<int > ignore (cbegin (graph[HOLE]), cend (graph[HOLE]));
111
+ for (int m = 0 ; m < size (graph); ++m) {
112
+ for (int c = 0 ; c < size (graph); ++c) {
113
+ degree[make_tuple (m, c, MOUSE)] = size (graph[m]);
114
+ degree[make_tuple (m, c, CAT)] = size (graph[c]) - ignore.count (c);
115
+ }
116
+ }
117
+ Lookup color;
118
+ queue<tuple<int , int , int >> q1;
119
+ queue<tuple<int , int , int >> q2;
120
+ for (int i = 0 ; i < size (graph); ++i) {
121
+ if (i == HOLE) {
122
+ continue ;
123
+ }
124
+ color[make_tuple (HOLE, i, CAT)] = MOUSE;
125
+ q1.emplace (HOLE, i, CAT);
126
+ for (const auto & t : {MOUSE, CAT}) {
127
+ color[make_tuple (i, i, t)] = CAT;
128
+ q2.emplace (i, i, t);
129
+ }
130
+ }
131
+ while (!empty (q1)) {
132
+ const auto [i, j, t] = q1.front (); q1.pop ();
133
+ for (const auto & [ni, nj, nt] : parents (graph, i, j, t)) {
134
+ if (color[make_tuple (ni, nj, nt)] != DRAW) {
135
+ continue ;
136
+ }
137
+ if (t == CAT) {
138
+ color[make_tuple (ni, nj, nt)] = MOUSE;
139
+ q1.emplace (ni, nj, nt);
140
+ continue ;
141
+ }
142
+ --degree[make_tuple (ni, nj, nt)];
143
+ if (!degree[make_tuple (ni, nj, nt)]) {
144
+ color[make_tuple (ni, nj, nt)] = MOUSE;
145
+ q1.emplace (ni, nj, nt);
146
+ }
147
+ }
148
+ }
149
+ while (!empty (q2)) {
150
+ const auto [i, j, t] = q2.front (); q2.pop ();
151
+ for (const auto & [ni, nj, nt] : parents (graph, i, j, t)) {
152
+ if (color[make_tuple (ni, nj, nt)] != DRAW) {
153
+ continue ;
154
+ }
155
+ if (t == MOUSE) {
156
+ color[make_tuple (ni, nj, nt)] = CAT;
157
+ q2.emplace (ni, nj, nt);
158
+ continue ;
159
+ }
160
+ --degree[make_tuple (ni, nj, nt)];
161
+ if (!degree[make_tuple (ni, nj, nt)]) {
162
+ color[make_tuple (ni, nj, nt)] = CAT;
163
+ q2.emplace (ni, nj, nt);
164
+ }
165
+ }
166
+ }
167
+ return color[make_tuple (MOUSE_START, CAT_START, MOUSE)];
168
+ }
169
+
170
+ private:
171
+ vector<tuple<int , int , int >> parents (const vector<vector<int >>& graph,
172
+ int m, int c, int t) {
173
+ vector<tuple<int , int , int >> result;
174
+ if (t == CAT) {
175
+ for (const auto & nm : graph[m]) {
176
+ result.emplace_back (nm, c, MOUSE ^ CAT ^ t);
177
+ }
178
+ } else {
179
+ for (const auto & nc : graph[c]) {
180
+ if (nc != HOLE) {
181
+ result.emplace_back (m, nc, MOUSE ^ CAT ^ t);
182
+ }
183
+ }
184
+ }
185
+ return result;
186
+ }
187
+ };
0 commit comments