题解: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();
}

posted @ 2024-10-19 08:56  cly312  阅读(19)  评论(0)    收藏  举报