Codeforces 986A Fair(最短路)
阿新 • • 發佈:2020-08-05
解題思路
經典的逆向思維,題目資料的特殊性提示我們利用好k只有100的條件。
每次用bfs把所有編號相同的點作為搜尋的起點,根據bfs的性質,每個點第一次被訪問的時的距離就是它離起點最近的距離。然後對於每個點,選出前s大即可。
程式碼
const int maxn = 1e5+10; struct E { int to, nxt; } e[maxn<<1]; bool vis[maxn]; int h[maxn], a[maxn], d[maxn][105], tot, n, m, k, s; void add(int a, int b) { e[++tot] = {b, h[a]}; h[a] = tot; } vector<int> tp[105]; void solve(int x) { for (int i = 1; i<=n; ++i) { d[i][x] = INF; vis[i] = false; } queue<P> qe; for (auto u : tp[x]) { d[u][x] = 0; qe.push({0, u}); vis[u] = true; } while(!qe.empty()) { int u = qe.front().second, w = qe.front().first; qe.pop(); ++w; for (int i = h[u]; i; i = e[i].nxt) { int v = e[i].to; if (!vis[v]) { vis[v] = true; qe.push({d[v][x]=w, v}); } } } } int main(void) { scanf("%d%d%d%d", &n, &m, &k, &s); for (int i = 1; i<=n; ++i) { scanf("%d", &a[i]); tp[a[i]].push_back(i); } for (int i = 0, u, v; i<m; ++i) { scanf("%d%d", &u, &v); add(u, v); add(v, u); } for (int i = 1; i<=k; ++i) solve(i); for (int i = 1; i<=n; ++i) { sort(d[i]+1, d[i]+1+k); int cost = 0; for (int j = 1; j<=s; ++j) cost += d[i][j]; printf(i==n ? "%d\n":"%d ", cost); } return 0; }