#include #define endl '\n' #define pb push_back using namespace std; const int maxn = 2e3 + 10; void speed() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } int n, m, p; long long d[maxn], cost[maxn][maxn]; int bestcost[maxn], bestpos[maxn]; vector < pair < int, int > > kids; /// opt, index vector < int > fromcity[maxn]; void read() { cin >> n >> m >> p; for (int i = 1; i <= p; ++ i) { cin >> d[i]; fromcity[d[i]].pb(i); } for (int i = 1; i <= n; ++ i) { bestcost[i] = 1e9; for (int j = 1; j <= 2000; ++ j) { cin >> cost[i][j]; if(bestcost[i] > cost[i][j]) { bestcost[i] = cost[i][j]; bestpos[i] = j; } } //cout << "city " << i << " has best spot in " << bestpos[i] << endl; for (auto kid: fromcity[i]) { kids.pb(make_pair(bestpos[i], kid)); // cout << "push back " << bestpos[i] << " to a kid " << kid << endl; } } sort(kids.begin(), kids.end()); // for (auto &[spot, id]: kids) // cout << spot << " " << id << endl; } vector < pair < int, int > > u[maxn]; int dist[maxn][maxn], from[maxn][maxn], used[maxn][maxn]; void dijkstra(int beg) { for (int i = 1; i <= n; ++ i) dist[beg][i] = 1e9; priority_queue < pair < int, int > > q; q.push(make_pair(0, beg)); dist[beg][beg] = 0; while(!q.empty()) { int w = q.top().second; q.pop(); if(used[beg][w])continue; used[beg][w] = 1; for (auto &[nb, cost]: u[w]) { if(used[beg][nb])continue; if(dist[beg][nb] > dist[beg][w] + cost) { dist[beg][nb] = dist[beg][w] + cost; from[beg][nb] = w; q.push(make_pair(-dist[beg][nb], nb)); } } } } void do_graph() { for (int i = 0; i < m; ++ i) { int uu, vv, ww; cin >> uu >> vv >> ww; u[uu].pb(make_pair(vv, ww)); u[vv].pb(make_pair(uu, ww)); } for (int i = 1; i<= n; ++ i) dijkstra(i); } int four[24][4] = { {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {0, 3, 2, 1}, {1, 0, 2, 3}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 2, 3, 0}, {1, 3, 0, 2}, {1, 3, 2, 0}, {2, 0, 1, 3}, {2, 0, 3, 1}, {2, 1, 0, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {2, 3, 1, 0}, {3, 0, 1, 2}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 1, 2, 0}, {3, 2, 0, 1}, {3, 2, 1, 0} }; int three[6][3] = { {0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 0, 1}, {2, 1, 0} }; int two [2][2] = { {0, 1}, {1, 0} }; int one[1][1] = { {0} }; int tmax, dp[maxn][maxn], action[maxn][maxn]; vector < int > route[maxn][maxn]; vector < int > recentpath; vector < int > make_path(int st, int fi) { vector < int > path; int v = fi; while(v != st) { path.pb(v); v = from[st][v]; } path.pb(st); reverse(path.begin(), path.end()); return path; } pair < long long, vector > fixed_route(vector < int > fixedpick, int moment) { vector < int > costs, dists; vector < int > path, addp; for (auto x: fixedpick) { costs.pb(cost[d[x]][moment]); } int curr = 1, allval = 0; for (auto kid: fixedpick) { int city = d[kid]; path.pb(city); dists.pb(dist[curr][city]); curr = city; } long long val = 0; for (int i = 0; i < costs.size(); ++ i) { allval += dists[i]; val += costs[i] * allval; } return make_pair(val, path); } int timep; bool cmp(int i, int j) { long long dist1 = dist[1][d[i]]; long long dist2 = dist[1][d[j]]; long long absdist = abs(dist1 - dist2); int gooo = dist[d[i]][d[j]]; long long cost1 = cost[d[i]][timep]; long long cost2 = cost[d[i]][timep]; long long abscost = abs(cost1 - cost2); if(absdist > abscost)return (dist1 < dist2); else return (cost1 < cost2); } long long solveroute(vector < int > pick, int moment) { timep = moment; recentpath.clear(); if(n == 20) { int sz = pick.size(), ways = 1; if(sz == 2)ways = 2; if(sz == 3)ways = 6; if(sz == 4)ways = 24; vector < int > bestpath; int bestres = 1e9; for (int way = 0; way < ways; ++ way) { vector < int > fixedpick; for (int idx = 0; idx < sz; ++ idx) { int curri, curr; if(sz == 1)curri = one[way][idx]; else if(sz == 2)curri = two[way][idx]; else if(sz == 3)curri = three[way][idx]; else curri = four[way][idx]; curr = pick[curri]; fixedpick.pb(curr); } pair < long long, vector < int > > curr_res = fixed_route(fixedpick, moment); if(curr_res.first < bestres) { bestres = curr_res.first; bestpath = curr_res.second; } } recentpath = bestpath; return bestres; } sort(pick.begin(), pick.end(), cmp); vector < int > fixedpick; fixedpick = pick; pair < long long, vector < int > > curr_res = fixed_route(fixedpick, moment); if(pick.size() == 4) { int picki = 0; int pickj = fixedpick.size()-1; pair < long long, vector < int > > impro = fixed_route(fixedpick, moment); if(impro.first < curr_res.first) { curr_res = impro; } } int bestres = curr_res.first; recentpath = curr_res.second; return bestres; } void solve() { for (int i = 0; i <= tmax; ++ i) { for (int j = 0; j <= p; ++ j) dp[i][j] = 1e9; } dp[0][0] = 0; for (int i = 1; i <= tmax; ++ i) { for (int j = 0; j <= p; ++ j) { dp[i][j] = dp[i-1][j]; action[i][j] = 0; } for (int j = 1; j <= p; ++ j) { for (int recent = 1; recent <= 4; ++ recent) { if(j < recent)continue; if(dp[i-1][j - recent] == 1e9)continue; vector < int > pick; for (int index = j; index > j - recent; -- index) pick.pb(kids[index-1].second); assert(pick.size() == recent); long long currcost = solveroute(pick, i); if(dp[i][j] > dp[i-1][j - recent] + currcost) { dp[i][j] = dp[i-1][j - recent] + currcost; action[i][j] = recent; route[i][j] = recentpath; } } } } } int tact[maxn]; vector < int > path[maxn]; vector < int > realroute(vector < int > planroute) { int curr = 1; vector < int > v; v.pb(curr); for (auto city: planroute) { v.pop_back(); //if(curr == city)continue; vector < int > add = make_path(curr, city); for (auto x: add) v.pb(x); curr = city; } return v; } int cntroute = 0; void roll() { int i = tmax, j = p; while(i > 0) { tact[i] = action[i][j]; path[i] = realroute(route[i][j]); if(tact[i])cntroute ++; j -= tact[i]; i --; } } int ki; void compute_moment(int moment, int take) { while(take --) { cout << kids[ki].second << " "; ki ++; } cout << endl; } int main() { freopen("transport.in","r",stdin); freopen("transport.out","w",stdout); // speed(); tmax = 2000; read(); do_graph(); solve(); roll(); cout << cntroute << endl; for (int i = 1; i <= tmax; ++ i) { if(!tact[i])continue; cout << i << " " << tact[i] << " " << path[i].size() << endl; compute_moment(i, tact[i]); for (auto x: path[i]) cout << x << " "; cout << endl; } return 0; }