codeforces CF986A Fair 图论 多源BFS
A. Fair
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≤105,1≤m≤105,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
*/