Codeforces 987D
题意:给你$n$个点$m$条边,$k$种货物,和一个$s$,之后让你从每个点开始走,收集到$s$种货物的最短路径长度。
因为$k$小只有$100$,所以我们直接把货物种类相同的用一个 vector 存起来,然后每次 BFS 每一种货物找他们到每个点的最短距离。每个点存每种货物到这个点的最短距离。之后询问排序这些距离取最小的$s$个即可。
知识点:数据小,就可以对着这个东西乱搞(暴力啊,存下来开桶什么的)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#define ms(i, j) memset(i, j, sizeof i)
#define LL long long
#define db double
using namespace std;
int n, m, k, s, whw[100000 + 5][100 + 5], a[100000 + 5];
queue<int> q;
vector<int> G[100000 + 5];
vector<int> gd[100 + 5];
void ins(int x, int y) {G[x].push_back(y), G[y].push_back(x);}
void clean() {
ms(whw, -1);
}
int solve() {
clean();
scanf("%d%d%d%d", &n, &m, &k, &s);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), gd[a[i]].push_back(i);
for (int x, y, i = 1; i <= m; i++) scanf("%d%d", &x, &y), ins(x, y);
for (int i = 1; i <= k; i++) {
if ((int)gd[i].size() == 0) continue;
for (int j = 0; j < (int)gd[i].size(); j++) q.push(gd[i][j]), whw[gd[i][j]][i] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int k = 0; k < (int)G[u].size(); k++) {
int v = G[u][k];
if (whw[v][i] < 0) whw[v][i] = whw[u][i] + 1, q.push(v);
}
}
}
for (int i = 1; i <= n; i++) {
sort(whw[i] + 1, whw[i] + 1 + k);
int ans = 0;
for (int j = 1; j <= s; j++) ans += whw[i][j];
printf("%d ", ans);
}
return 0;
}
int main() {
solve();
return 0;
}