[CodeForces]986A Fair

大意:给一张图,每个图上有一个数,问以每个点为源点,经过的点包含k种数字的最小距离。
显然跑最短路会T,但我们注意到边权一定。某次学校考试就是类似题,可以bfs做,复杂度O(n),每种货物做一次,复杂度O(kn),n=1e5,k=100,稳了。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <queue>
using namespace std;
const int N=1e5+8;
int n,m,ecnt,head[N],k,s,dis[N][105],cnt;
struct Edge{int to,nxt;}e[N<<1];
void add(int bg,int ed){e[++ecnt].to=ed;e[ecnt].nxt=head[bg];head[bg]=ecnt;}
vector<int>S[105];
void bfs(int x){
	queue<int>q;
	for(int i=0;i<S[x].size();i++)q.push(S[x][i]),dis[S[x][i]][x]=0;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u],v;i;i=e[i].nxt) {
			v=e[i].to;
			if (dis[v][x]>dis[u][x]+1) {dis[v][x]=dis[u][x]+1;q.push(v);}
		}
	}
}
int main() {
	memset(dis,0x3f,sizeof dis);
	scanf("%d%d%d%d",&n,&m,&k,&s);
	for(int i=1,x;i<=n;i++) {scanf("%d",&x);S[x].push_back(i);}
	for(int i=1,u,v;i<=m;i++){scanf("%d%d",&u,&v);add(u,v);add(v,u);}
	for(int i=1;i<=k;i++) 
		bfs(i);
	for(int i=1;i<=n;i++) {
		// int mn=0x3f3f3f3f;
		sort(dis[i]+1,dis[i]+1+k);
		int ans=0;
		for(int j=1;j<=s;j++) ans+=dis[i][j];
		printf("%d ",ans);
	}
}
posted @ 2018-07-06 20:18  SWHsz  阅读(133)  评论(0编辑  收藏  举报