题解:SP99 BUS - Bus
先用中国剩余定理处理出所有司机之间的相遇时间,然后独立考虑每条新闻,找出所有司机得知这条新闻所需的最短时间。使用类似于 Dijkstra 算法(每次选择一对司机,一个已经知道,另一个不知道)来更新即可。
#include<bits/stdc++.h>
using namespace std;
int mod(int a, int b) {
return ((a%b)+b)%b;
}
int extended_euclid(int a, int b, int &x, int &y) {
int xx = y = 0;
int yy = x = 1;
while (b) {
int q = a/b;
int t = b; b = a%b; a = t;
t = xx; xx = x-q*xx; x = t;
t = yy; yy = y-q*yy; y = t;
}
return a;
}
int solve_one(int n, int start,int (&lcm)[50][50],vector<int> (&meet_times)[50][50]) {
vector<int> vis(50, 0);
vector<int> when(50, INT_MAX);
int num_vis = 0;
when[start] = 0;
for (;;) {
int cur = -1;
for (int i = 0; i < n; i++) {
if (!vis[i] && (cur == -1 || when[i] < when[cur])) {
cur = i;
}
}
if (when[cur] == INT_MAX) return INT_MAX;
const int time = when[cur];
vis[cur] = 1;
if (n == ++num_vis) return time;
for (int next = 0; next < n; next++) {
if (vis[next]) continue;
if (meet_times[cur][next].empty()) continue;
const int tmod = time % lcm[cur][next];
int next_mod = meet_times[cur][next][0];
for (const int meet_time : meet_times[cur][next]) {
if (meet_time >= tmod) {
next_mod = meet_time;
break;
}
}
const int next_time = time + mod(next_mod - tmod, lcm[cur][next]);
when[next] = min(when[next], next_time);
}
}
}
void solve() {
int n; cin >> n;
if (n == 0) exit(0);
vector<int> routes[50];
for (int i = 0; i < n; i++) {
int s; cin >> s;
while (s--) {
int x; cin >> x;
routes[i].push_back(x);
}
}
int lcm[50][50];
unordered_multimap<int, int> stop_to_index[50];
vector<int> meet_times[50][50];
for (int i = 0; i < n; i++) {
for (size_t j = 0; j < routes[i].size(); j++) {
stop_to_index[i].emplace(routes[i][j], j);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) continue;
const int a = routes[i].size();
const int b = routes[j].size();
int x, y;
const int gcd = extended_euclid(a, b, x, y);
lcm[i][j] = a * b / gcd;
auto& mt = meet_times[i][j];
for (int k = 0; k < a; k++) {
const auto p = stop_to_index[j].equal_range(routes[i][k]);
for (auto it = p.first; it != p.second; ++it) {
const int m = it->second;
if ((k - m) % gcd) continue;
mt.push_back(mod(x*m*a + y*k*b, a*b) / gcd);
}
}
sort(mt.begin(), mt.end());
mt.erase(unique(mt.begin(), mt.end()), mt.end());
}
}
int result = 0;
for (int i = 0; i < n; i++) {
result = max(result, solve_one(n, i, lcm, meet_times));
}
if (result == INT_MAX) {
cout << "NEVER\n";
} else {
cout << result << '\n';
}
}
int main() {
for (;;) solve();
}

浙公网安备 33010602011771号