#include using namespace std; constexpr int N = 47, R = 1000, M = 400, K = 25; constexpr int INF = 1e9; constexpr int MAX_TIME_SLOTS = 182; constexpr int MAX_FLIGHTS = 2000; struct Flight { int u, s, v, t; }; // スロット(0~180)を "HH:MM" 形式の文字列に変換 string to_time_str(int t) { int h = 6 + t / 12; int m = (t % 12) * 5; char buf[6]; snprintf(buf, sizeof(buf), "%02d:%02d", h, m); return string(buf); } struct Input { array x, y, w; array a, s, b, t; array, N> valid_dist{}; array, N> weight{}; long long total_W = 0; Input() { int _; cin >> _ >> _; for (int i = 0; i < N; ++i) cin >> x[i] >> y[i] >> w[i]; cin >> _; string s_str, t_str; for (int i = 0; i < M; ++i) { cin >> a[i] >> s_str >> b[i] >> t_str; --a[i], --b[i]; s[i] = (stoi(s_str.substr(0, 2)) - 6) * 12 + stoi(s_str.substr(3, 2)) / 5; t[i] = (stoi(t_str.substr(0, 2)) - 6) * 12 + stoi(t_str.substr(3, 2)) / 5; } for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { if (i == j) continue; long long dx = x[i] - x[j]; long long dy = y[i] - y[j]; if (dx * dx + dy * dy >= (R * R) / 16) { valid_dist[i][j] = true; weight[i][j] = (long long)w[i] * w[j]; total_W += weight[i][j] * 21; } } } } int get_duration(int u, int v) const { double dx = x[u] - x[v]; double dy = y[u] - y[v]; double d = sqrt(dx * dx + dy * dy); double minutes = 60.0 * d / 800.0 + 40.0; return (int)ceil(minutes / 5.0 - 1e-9); } }; // 計算用のワークスペース struct ComputeSciWorkspace { array, N> head; array nxt; array, N> reach; }; // 限界利益探索用の巨大配列を保持するワークスペース struct MarginalGainWorkspace { array, N>, N> current_s_ci; array, N>, N> edge_gain; array, N> dp; array, N> nxt_v; array, N> dur; }; // 共通関数:フライト集合に対する限界出発時刻 (s_ci) を計算する void compute_s_ci(const Input& in, const vector& flights, array, N>, N>& s_ci, ComputeSciWorkspace& ws) { for (int u = 0; u < N; ++u) { for (int dst = 0; dst < N; ++dst) { s_ci[u][dst].fill(-INF); } } for (int u = 0; u < N; ++u) ws.head[u].fill(-1); ws.nxt.fill(-1); for (int i = 0; i < (int)flights.size(); ++i) { int u = flights[i].u; int s = flights[i].s; ws.nxt[i] = ws.head[u][s]; ws.head[u][s] = i; } for (int dst = 0; dst < N; ++dst) { for (int T_idx = 0; T_idx < 21; ++T_idx) { int T_target = 60 + T_idx * 6; for (int u = 0; u < N; ++u) ws.reach[u].fill(false); for (int t = 0; t <= T_target; ++t) ws.reach[dst][t] = true; for (int t = T_target; t >= 0; --t) { for (int u = 0; u < N; ++u) { if (t + 1 <= 180 && ws.reach[u][t + 1]) ws.reach[u][t] = true; for (int e = ws.head[u][t]; e != -1; e = ws.nxt[e]) { int v = flights[e].v; int arr_time = flights[e].t; if (arr_time <= T_target && ws.reach[v][arr_time]) { ws.reach[u][t] = true; } } } } for (int u = 0; u < N; ++u) { if (u == dst || !in.valid_dist[u][dst]) continue; for (int t = T_target; t >= 0; --t) { if (ws.reach[u][t]) { s_ci[u][dst][T_idx] = t; break; } } } } } } struct RivalSchedule { array, N>, N> s_sq; RivalSchedule(const Input& in, ComputeSciWorkspace& ws) { vector r_flights; r_flights.reserve(M); for (int i = 0; i < M; ++i) r_flights.push_back({in.a[i], in.s[i], in.b[i], in.t[i]}); compute_s_ci(in, r_flights, s_sq, ws); } }; // 限界利益(Marginal Gain)に基づく逐次最長路アルゴリズム array, K> solve_marginal_gain(const Input& in, const RivalSchedule& rival, ComputeSciWorkspace& c_ws, MarginalGainWorkspace& mg_ws) { array, K> circle_flights; vector all_my_flights; all_my_flights.reserve(MAX_FLIGHTS); for (int u = 0; u < N; ++u) { for (int v = 0; v < N; ++v) { mg_ws.dur[u][v] = (u != v) ? in.get_duration(u, v) : 0; } } for (int k = 0; k < K; ++k) { compute_s_ci(in, all_my_flights, mg_ws.current_s_ci, c_ws); for (int u = 0; u < N; ++u) { for (int v = 0; v < N; ++v) mg_ws.edge_gain[u][v].fill(0); } for (int u = 0; u < N; ++u) { for (int dst = 0; dst < N; ++dst) { if (!in.valid_dist[u][dst]) continue; for (int T_idx = 0; T_idx < 21; ++T_idx) { int s_sq_val = rival.s_sq[u][dst][T_idx]; int s_ci_val = mg_ws.current_s_ci[u][dst][T_idx]; if (s_ci_val > s_sq_val) continue; int min_s = max(0, s_sq_val + 1); int T_target = 60 + T_idx * 6; for (int v = 0; v < N; ++v) { if (u == v) continue; int max_t = (v == dst) ? T_target : mg_ws.current_s_ci[v][dst][T_idx]; if (max_t < 0) continue; int max_s = min(180 - mg_ws.dur[u][v], max_t - mg_ws.dur[u][v]); if (min_s <= max_s) { mg_ws.edge_gain[u][v][min_s] += in.weight[u][dst]; if (max_s + 1 <= 180) mg_ws.edge_gain[u][v][max_s + 1] -= in.weight[u][dst]; } } } } } for (int u = 0; u < N; ++u) { for (int v = 0; v < N; ++v) { if (u == v) continue; long long current_val = 0; for (int s = 0; s <= 180; ++s) { current_val += mg_ws.edge_gain[u][v][s]; mg_ws.edge_gain[u][v][s] = current_val; } } } for (int u = 0; u < N; ++u) { mg_ws.dp[u].fill(0); mg_ws.nxt_v[u].fill(-1); } for (int t = 180; t >= 0; --t) { for (int u = 0; u < N; ++u) { if (t + 1 <= 180) { mg_ws.dp[u][t] = mg_ws.dp[u][t + 1]; mg_ws.nxt_v[u][t] = -1; } for (int v = 0; v < N; ++v) { if (u == v) continue; int t_next = t + mg_ws.dur[u][v]; if (t_next <= 180) { long long gain = mg_ws.edge_gain[u][v][t]; if (gain + mg_ws.dp[v][t_next] > mg_ws.dp[u][t]) { mg_ws.dp[u][t] = gain + mg_ws.dp[v][t_next]; mg_ws.nxt_v[u][t] = v; } } } } } long long best_start_val = -1; int start_u = 0; for (int u = 0; u < N; ++u) { if (mg_ws.dp[u][0] > best_start_val) { best_start_val = mg_ws.dp[u][0]; start_u = u; } } int curr_u = start_u, curr_t = 0; while (curr_t <= 180) { int next_city = mg_ws.nxt_v[curr_u][curr_t]; if (next_city != -1) { int d = mg_ws.dur[curr_u][next_city]; Flight f = {curr_u, curr_t, next_city, curr_t + d}; circle_flights[k].push_back(f); all_my_flights.push_back(f); curr_u = next_city; curr_t += d; } else { curr_t += 1; } } } return circle_flights; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); Input in; auto c_ws = make_unique(); auto mg_ws = make_unique(); RivalSchedule rival(in, *c_ws); auto circle_flights = solve_marginal_gain(in, rival, *c_ws, *mg_ws); for (int k = 0; k < K; ++k) { cout << circle_flights[k].size() << "\n"; for (const auto& f : circle_flights[k]) { cout << f.u + 1 << " " << to_time_str(f.s) << " " << f.v + 1 << " " << to_time_str(f.t) << "\n"; } } return 0; }