$ \rightarrow $ 戳我进CF原题

A. Fair

time limit per test: 2 seconds
memory limit per test: 512 megabytes
input: standard input
output: standard output

 

Some company is going to hold a fair in Byteland.
There are $ n $ towns in Byteland and $ m $ two-way roads between towns.
Of course, you can reach any town from any other town using roads.
 
There are $ k $ types of goods produced in Byteland and every town produces only one type.
To hold a fair you have to bring at least $ s $ different types of goods.
It costs $ d(u,v) $ coins to bring goods from town $ u $ to town $ v $
where $ d(u,v) $ is the length of the shortest path from $ u $ to $ v $ .
Length of a path is the number of roads in this path.
 
The organizers will cover all travel expenses but they can choose the towns to bring goods from.
Now they want to calculate minimum expenses to hold a fair in each of $ n $ towns.
 

Input

There are $ 4 $ integers $ n,m,k,s $ in the first line of input $ (1 \le n \le 10^5,0 \le m \le 10^5,1\le s \le k \le min(n,100)) $
— the number of towns, the number of roads, the number of different types of goods,
the number of different types of goods necessary to hold a fair.
 
In the next line there are $ n $ integers $ a_1,a_2,\dots,a_n(1 \le a_i \le k) $ ,
where $ a_i $ is the type of goods produced in the $ i $ -th town.
It is guaranteed that all integers between $ i $ and $ k $ occur at least once among integers $ a_i $ .
 
In the next $ m $ lines roads are described.
Each road is described by two integers $ u,v (1 \le u,v \le n,u \not= v) $ — the towns connected by this road.
It is guaranteed that there is no more than one road between every two towns.
It is guaranteed that you can go from any town to any other town via roads.
 

Output

Print $ n $ numbers,
the $ i $ -th of them is the minimum number of coins you need to spend on travel expenses to hold a fair in town $ i $ .
Separate numbers with spaces.
 

Examples

input1
 5 5 4 3
 1 2 4 3 2
 1 2
 2 3
 3 4
 4 1
 4 5
output1
 2 2 2 2 3 

input2
 7 6 3 2
 1 2 3 3 2 2 1
 1 2
 2 3
 3 4
 2 5
 5 6
 6 7
output2
 1 1 1 2 2 1 1 

 

Note

Let's look at the first sample.
To hold a fair in town $ 1 $ you can bring goods from towns $ 1(0 \quad coins),2(1 \quad coin) $ and $ 4(1 \quad coin) $ .
Total numbers of coins is $ 2 $ .
 
Town $ 2 $ : Goods from towns $ 2(0),1(1),3(1) $. Sum equals $ 2 $ .
 
Town $ 3 $ : Goods from towns $ 3(0),2(1),4(1) $. Sum equals $ 2 $ .
 
Town $ 4 $ : Goods from towns $ 4(0),1(1),5(1) $. Sum equals $ 2 $ .
 
Town $ 5 $ : Goods from towns $ 5(0),4(1),3(2) $. Sum equals $ 3 $ .

 

题目描述

一些公司将在Byteland举办商品交易会(or博览会?)。在Byteland有 n个城市,城市间有 m条双向道路。
当然,城镇之间两两连通。 Byteland生产的货物有 k种类型,每个城镇只生产一种。
为了举办商品交易会,你必须至少带来s种不同类型的商品。
将货物从 $ u $ 镇带到城镇 $ v $ 将花费 $ d(u,v) $ 的费用,其中 $ d(u,v) $ 是从 u到 v的最短路径的长度。
路径的长度是这个路径中的道路的数量。
组织者将支付所有的运输费用,但他们可以选择从哪些城镇带来货物。
现在他们想计算每个城镇举办商品交易会的最小费用。
 

输入输出格式

输入格式:

第一行 $ 4 $ 个整数 $ n,m,k,s (1≤n≤10^5,1≤m≤10^5,1≤k≤min(n,100) ) $
——分别表示 城镇数,道路数,生产的货物数,举办商品交易会所需的货物数。
接下来一行 $ n $ 个整数 $ a_1,a_2,...,a_n(1≤a≤k) , a_i $ 是第 i个城镇生产的商品种类.
保证 $ 1 $ 和 $ k $ 之间的所有整数在整数 $ a_i $ 中至少出现一次。
接下来 $ m $ 行表示道路。每行两个整数 $ u,v(1≤u,v≤n,u≠v) $ 表示 $ u,v $ 之间有一条双向道路。
保证每两个城镇之间只有一条路。并且城镇之间两两连通。
 

输出格式:

输出 $ n $ 个数。
第 $ i $ 个数表示在第 i个城镇举办商品交易会所需花在运输上的最小费用。数与数之间用空格分开。
 

@来自洛谷U57304 jzzcjb

 

题解

  • 每种货物分开做

  • 对于第 $ i $ 种货物 $ (1 \le i \le k ) $

  • 把所有生产第 $ i $ 种货物的点入队执行一次多源 $ BFS $

  • 得到每个点距离每种货物的最短距离

  • $ O(nk) $
     

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
struct Data{ int nsp,u,ds; }data;
struct edge{ int v,nxt; }e[200005];
int n,m,k,s,head[100005],tot,dis[100005][105],anss[105],ans;
bool vis[100005][105];
void add(int u,int v){ e[++tot].v=v; e[tot].nxt=head[u]; head[u]=tot; }
queue<Data>q;
void bfs(){
    while(!q.empty()){
        int u=q.front().u,nsp=q.front().nsp,ds=q.front().ds; q.pop();
        for(int i=head[u];i;i=e[i].nxt)
            if(!vis[e[i].v][nsp]){
                vis[e[i].v][nsp]=1;
                dis[e[i].v][nsp]=ds+1;
                data.u=e[i].v;
                data.nsp=nsp;
                data.ds=ds+1;
                q.push(data);
            }
    }
}
int main(){
    scanf("%d %d %d %d",&n,&m,&k,&s);
    memset(dis,0x3f,sizeof(dis));
    for(int sp,i=1;i<=n;++i){
        scanf("%d",&sp);
        vis[i][sp]=1;
        dis[i][sp]=0;
        data.nsp=sp;
        data.u=i;
        data.ds=0;
        q.push(data);
    }
    for(int u,v,i=1;i<=m;++i){
        scanf("%d %d",&u,&v);
        add(u,v); add(v,u);
    }
    bfs();
    for(int i=1;i<=n;++i){
        ans=0;
        for(int j=1;j<=k;++j) anss[j]=dis[i][j];
        nth_element(anss+1,anss+1+s,anss+1+k);
        for(int j=1;j<=s;++j) ans+=anss[j];
        printf("%d ",ans);
    }
    return 0;
}
/*
#        40057983
When     2018-07-07 13:20:15 
Who      PotremZ
Problem  A - Fair
Lang     GNU C++
Verdict  Accepted
Time     888 ms
Memory   73400 KB
*/

转载于:https://www.cnblogs.com/PotremZ/p/CF986A.html

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐