codeforces 987 D. Fair
2 seconds
512 megabytes
standard input
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.
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, \ldots, 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 $$$1$$$ 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 \ne 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.
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.
5 5 4 3
1 2 4 3 2
1 2
2 3
3 4
4 1
4 5
2 2 2 2 3
7 6 3 2
1 2 3 3 2 2 1
1 2
2 3
3 4
2 5
5 6
6 7
1 1 1 2 2 1 1
Let's look at the first sample.
To hold a fair in town $$$1$$$ you can bring goods from towns $$$1$$$ ($$$0$$$ coins), $$$2$$$ ($$$1$$$ coin) and $$$4$$$ ($$$1$$$ 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$$$.
【题意】
$$$n$$$个结点,$$$m$$$条边,$$$s$$$种商品,每个结点含有一种商品,且保证所有商品至少被一个结点包含。对于每个结点,选择至少$$$k$$$个结点,使他们包含至少$$$k$$$种商品,且到该结点的总距离和最小。
【思路】
结点和边的数量为1e5,而商品个数只有100,如果从每个结点出发直到寻找$$$k$$$个商品为止,那么这样做其实并不划算,其原因在于很难决定最近的商品在哪条路上,需要搜索到很深的地方,而且含有相同商品的城市会被反复访问。为了节约时间,可以预先从商品出发进行bfs,那么经过的城市都是最近的,这样处理以后每个城市就知道,自己到每个商品的最近距离,要凑齐$$$k$$$个商品只需要选择前k个最小的距离就行了。
【注意】
这里的bfs需要抽象理解一下,假如对$$$i$$$号商品进行bfs,那么第一步就要直接转移到所有含$$$i$$$的城市,然后就是平常的bfs了,每次扩展1个距离,遍历完所有城市后,每个城市就都有一个获得$$$i$$$的最短距离了。
【代码】
#include<stdio.h>
#include<queue>
#include<memory.h>
#include<algorithm>
#include<vector> using std::queue;
using std::vector;
using std::sort; vector<int> t[];
#define N 100005
vector<int>node[N];
int cost[N][] = { };
int vis[N];
void bfs(int si) {
queue<int>help; int sz = t[si].size();
//将含si的所有城市加入到bfs的第一次转移
for (int i = ; i < sz; ++i) {
int next=t[si][i];
help.push(next);
vis[next] = ;
}
//bfs继续转移
for (int cnt = ; !help.empty();cnt++) {
int sz = help.size();
for (int i = ; i < sz; ++i) {
int next = help.front(); help.pop();
int nsz = node[next].size();
for (int t = ; t < nsz; ++t) {
int pnext = node[next][t];
if (vis[pnext] == )continue;
vis[pnext] = ;
cost[pnext][si] = cnt;
help.push(pnext);
}
}
}
} int main() {
int n, m, s, k;
scanf("%d %d %d %d", &n, &m, &s, &k);
int a0,a1;
for (int i = ; i <= n; ++i) {
scanf("%d", &a0);
t[a0].push_back(i);
}
for (int i = ; i < m; ++i) {
scanf("%d %d", &a0, &a1);
node[a0].push_back(a1);
node[a1].push_back(a0);
}
for (int i = ; i <= s; ++i) {
memset(vis, , sizeof vis);
bfs(i);
}
for (int i = ; i <= n; ++i) {
//排序并选择前k个
sort(cost[i] + , cost[i] + + s);
int sum = ;
for (int t = ; t <= k; ++t)
sum += cost[i][t];
printf("%d ", sum);
}
}
codeforces 987 D. Fair的更多相关文章
- codeforces 897A Scarborough Fair 暴力签到
codeforces 897A Scarborough Fair 题目链接: http://codeforces.com/problemset/problem/897/A 思路: 暴力大法好 代码: ...
- CF 987 D. Fair
D. Fair http://codeforces.com/contest/987/problem/D 题意: n个城镇m条道路,(保证没有重边,两个城镇间可以到达),每个城镇拥有的特产ai(可能多个 ...
- [Codeforces Round 486A] Fair
[题目链接] https://codeforces.com/contest/986/problem/A [算法] 用dist(i,j)表示第i种食物运到第j个城市需要的最小代价 将所有特产为第i中食物 ...
- CodeForces 1084D The Fair Nut and the Best Path
The Fair Nut and the Best Path 题意:求路径上的 点权和 - 边权和 最大, 然后不能存在某个点为负数. 题解: dfs一遍, 求所有儿子走到这个点的最大值和次大值. 我 ...
- CodeForces - 1073D Berland Fair
XXI Berland Annual Fair is coming really soon! Traditionally fair consists of nnbooths, arranged in ...
- Codeforces 987 K预处理BFS 3n,7n+1随机结论题/不动点逆序对 X&Y=0连边DFS求连通块数目
A /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_bac ...
- Codeforces 1083E The Fair Nut and Rectangles
Description 有\(N\)个左下定点为原点的矩阵, 每个矩阵\((x_i,~y_i)\)都有一个数\(a_i\)表示其花费. 没有一个矩阵包含另一个矩阵. 现要你选出若干个矩阵, 使得矩阵组 ...
- Codeforces 1083B The Fair Nut and Strings
Description 给定两个由 \('a'\), \('b'\) 组成的字符串 \(a\), \(b\),以及两个整数 \(n\) 和 \(k\) \(n\) 表示字符串 \(a\),\(b\) ...
- Codeforces 987 F - AND Graph
F - AND Graph 思路: 首先,x & (~x) == 0 其次,~x 的 子集 y = ((~x) ^ (1<<k)), 0<= k < n(如果k这一位是 ...
随机推荐
- shiro中基于注解实现的权限认证过程
授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限等等. 一.用户权限模型 为实现一个较为灵活的用户权限数据模 ...
- BZOJ1053_反素数_KEY
题目传送门 初看这道题,以为是一道挺难的题目,但仔细看发现,不是只要爆搜就好了吗? 只需要对前12个素数进行爆搜即可. 一个数的因数个数=素数次数+1全部乘起来. code: /*********** ...
- BZOJ1821_Group部落划分_KEY
题目传送门 这是一道并查集的题目,相信很多人都看出来了. 用一个类似Kurskal的东西求出最近的最大值. 对于一些可以划分在同一个部落里的边,我们一定是优先选择短边合并. code: /****** ...
- Python|一文简单看懂 深度&广度 优先算法
一.前言 以后尽量每天更新一篇,也是自己的一个学习打卡!加油!今天给大家分享的是,Python里深度/广度优先算法介绍及实现. 二.深度.广度优先算法简介 1. 深度优先搜索(DepthFirstSe ...
- Java学习 · 初识 容器和数据结构
容器和数据结构 1. 集合的引入 a) 集合的使用场景:需要将一些相同结构的个体整合到一起时 i. 新闻列表 ii. 邮件列表 iii. ...
- win7下本地运行spark以及spark.sql.warehouse.dir设置
SparkSession spark = SparkSession .builder() .master("local[*]") .enableHiveSupport() .con ...
- netty in action 笔记 二
netty的数据容器 网络数据的基本单位大多为字节,Java NIO 提供了ByteBuffer 作为它的字节容器,但使用起来过于复杂和繁琐.在Netty中, ByteBuffer 替代品是ByteB ...
- codeforces 319B Psychos in a Line(模拟)
There are n psychos standing in a line. Each psycho is assigned a unique integer from 1 to n. At eac ...
- 单源最短路——dijkstra算法
Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 问 ...
- UML设计(团队作业)
UML设计 一.团队信息 1.队名 读完文章再睡觉 2.团队成员的学号与姓名 学号 姓名 211606381 吴伟华(队长) 211606369 蔺皓雯 211606340 杨池宇 211606372 ...