CF 987 D. Fair

时间:2023-03-09 00:00:59
CF 987 D. Fair

D. Fair

http://codeforces.com/contest/987/problem/D

题意:

  n个城镇m条道路,(保证没有重边,两个城镇间可以到达),每个城镇拥有的特产ai(可能多个城镇有相同特产)。总共有k种不同特产。每个城镇举办展会需要至少s种特产,一份特产从一个城镇运到另一个城镇的花费为最短路(每次只能运一个)。求出在每个城镇举办展会的最小花费。

分析:

  bfs。

  如果直接枚举每个城镇作为举办展会,然后计算到每个特产的最短路,取出前s个,复杂度n^2。

  发现k<=100,所以可以反过来枚举,枚举每特产到每个城镇的最短路,多源bfs跑一下,最后枚举每个诚镇计算答案。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
const int INF = 1e9; struct Edge{
int to, nxt;
}e[N << ];
int head[N], En, dis[N][], q[N];
vector<int> vec[]; void add_edge(int u,int v) {
++En; e[En].to = v; e[En].nxt = head[u]; head[u] = En;
++En; e[En].to = u; e[En].nxt = head[v]; head[v] = En;
} void bfs(int x) {
int L = , R = ;
for (int sz = vec[x].size(), i = ; i < sz; ++i) {
q[++R] = vec[x][i];
dis[vec[x][i]][x] = ;
}
while (L <= R) {
int u = q[L++];
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (dis[v][x] == INF) {
dis[v][x] = dis[u][x] + ;
q[++R] = v;
}
}
}
} int main() {
int n = read(), m = read(), k = read(), s = read();
for (int i = ; i <= n; ++i) vec[read()].push_back(i);
for (int i = ; i <= m; ++i) {
int u = read(), v = read();
add_edge(u, v);
}
for (int i = ; i <= k; ++i) {
for (int j = ; j <= n; ++j) dis[j][i] = INF;
bfs(i);
} for (int i = ; i <= n; ++i) {
int ans = ;
sort(dis[i] + , dis[i] + k + );
for (int j = ; j <= s; ++j) ans += dis[i][j];
printf("%d ",ans);
} return ;
}