[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);
    }
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9275385.html