题目大意:
n个点m条边,边权为1,d(u,v)=u,v最短路
P(u)每个点产生的物品已知,找s个点是p两两不同
并且找到最短的一条路
solution:
多源bfs,每种货物分开做,把所有生产第i种的点入队做bfs
得到每个点距离每种货物最短的距离
排序把前s小的加起来
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define LL long long
#define maxn 100005
using namespace std;
int n,m,k,s,cnt,head[maxn],dis[maxn][105],a[maxn],q[maxn];
bool vis[maxn];
inline int rd(){
int x=0,f=1; char c=' ';
while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();}
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
struct EDGE{
int to,nxt;
}edge[maxn*2];
void add(int x,int y){
cnt++;
edge[cnt].to=y;
edge[cnt].nxt=head[x];
head[x]=cnt;
}
void bfs(){
memset(dis,0x3f,sizeof dis);
for(int now=1;now<=k;now++){
int h=0,t=0;
for(int i=1;i<=n;i++){
if(a[i]==now) q[++t]=i,dis[i][now]=0;
}
while(h<t){
h++; int u=q[h];
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(dis[v][now]>dis[u][now]+1) q[++t]=v,dis[v][now]=dis[u][now]+1;
}
}
}
}
int main(){
n=rd(); m=rd(); k=rd(); s=rd();
for(int i=1;i<=n;i++) a[i]=rd();
for(int i=1;i<=m;i++){
int x=rd(),y=rd();
add(x,y); add(y,x);
}
bfs();
for(int i=1;i<=n;i++){
LL ans=0;//这地方没开long longWA了一次···
sort(dis[i]+1,dis[i]+k+1);
for(int j=1;j<=s;j++) ans+=dis[i][j];
printf("%lld ",ans);
}
return 0;
}