codeforces987D bfs跑最短路

http://codeforces.com/contest/987/problem/D

题意:有N个城市,M条双向道路连接两个城市(边权为 1 ),整个图保证连通。有K种物品,但每个城市只有一种,现在它们都需要S种物品来举办展览,可以去其他城市获取该城市的物品,花费是两城市之间的最短路径长度。求每个城市举办展览的最小花费。

分析:如果我们正面求解肯定TLE因为1e5数据很大,不妨我们逆向考虑一下,考虑物品 i 到小镇 j 的距离(dist [ j ][ x ]表示  )即以物品i为源点跑bfs;最后对k个物品进行bfs走最短路,然后不断更新与其他小镇的距离,对后进行sort排序一下取前s个即可。

代码::

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD=998244353;
const int maxn=1e5+5;
const int maxnn=105;
int dist[maxn][maxnn];//记录物品i到小镇的距离
vector<int> V[maxn];
int ma[maxn];
int res[maxn];
bool vis[maxn];//标记
void bfs(int x,int y)
{
    queue<int>que;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=y;i++)
    {
        if(ma[i]==x){//以物品  i 为源点进行最短路;同时标记防止下次搜索找到同样的物品           
             vis[i]=1;           
             que.push(i);       
          }   
     }
    while(!que.empty())
    {
        int val=que.front();
        que.pop();
        for(int i=0;i<V[val].size();i++)
        {
            int key=V[val][i];
            if(!vis[key]){
                vis[key]=1;
                dist[key][x]=dist[val][x]+1;
                que.push(key);
            }
        }
    }
}
int main()
{
    int n,m,s,k;
    scanf("%d%d%d%d",&n,&m,&k,&s);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&ma[i]);
    }
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        V[a].push_back(b);
        V[b].push_back(a);
    }
    for(int i=1;i<=k;i++)
    {
        bfs(i,n);
    }
    for(int i=1;i<=n;i++)
    {
        sort(dist[i]+1,dist[i]+k+1);
        res[i]=0;
        for(int j=1;j<=s;j++)
        {
            res[i]+=dist[i][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
        printf("%d ",res[i]);
    }
    return 0;
}
纵使单枪匹马,也要勇闯天涯
原文地址:https://www.cnblogs.com/sj-gank/p/11384911.html