多源BFS--CF986A

题目大意:
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;
}

猜你喜欢

转载自blog.csdn.net/sizeof_you/article/details/80958115