题目:http://codeforces.com/contest/986/problem/A
如果从每个村庄开始bfs找货物,会超时。
发现k较小。那就从货物开始bfs,给村庄赋上dis[ 该货物 ]。
但这样还是n^2。考虑有相同货物的村庄,其实可以一起bfs。就是多源bfs。这样就是n*k的了。
多源bfs就是把一些起始点的dis全赋了初值0,然后都放进队列里,之后正常bfs。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+5,K=105; int n,m,k,s,head[N],xnt,dis[N][K],a[N],q[K][N],h,t[K]; struct Ed{ int next,to; Ed(int n=0,int t=0):next(n),to(t) {} }ed[N<<1]; void add(int x,int y) { ed[++xnt]=Ed(head[x],y);head[x]=xnt; ed[++xnt]=Ed(head[y],x);head[y]=xnt; } int main() { scanf("%d%d%d%d",&n,&m,&k,&s); memset(dis,0x3f,sizeof dis); for(int i=1;i<=n;i++) { scanf("%d",&a[i]);dis[i][a[i]]=0; q[a[i]][++t[a[i]]]=i; } int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y);add(x,y); } for(int i=1;i<=k;i++) { h=1; while(h<=t[i]) { int k=q[i][h++]; for(int j=head[k],v;j;j=ed[j].next) if(dis[v=ed[j].to][i]>dis[k][i]+1) { dis[v][i]=dis[k][i]+1;q[i][++t[i]]=v; } } } for(int i=1;i<=n;i++) { int ans=0;sort(dis[i]+1,dis[i]+k+1); for(int j=1;j<=s;j++)ans+=dis[i][j]; printf("%d ",ans); } return 0; }