codeforces 987 D. Fair
Posted tobyw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 987 D. 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.
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 e 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$$$的最短距离了。
【代码】
1 #include<stdio.h> 2 #include<queue> 3 #include<memory.h> 4 #include<algorithm> 5 #include<vector> 6 7 using std::queue; 8 using std::vector; 9 using std::sort; 10 11 vector<int> t[101]; 12 #define N 100005 13 vector<int>node[N]; 14 int cost[N][101] = { 0 }; 15 int vis[N]; 16 void bfs(int si) { 17 queue<int>help; 18 19 int sz = t[si].size(); 20 //将含si的所有城市加入到bfs的第一次转移 21 for (int i = 0; i < sz; ++i) { 22 int next=t[si][i]; 23 help.push(next); 24 vis[next] = 1; 25 } 26 //bfs继续转移 27 for (int cnt = 1; !help.empty();cnt++) { 28 int sz = help.size(); 29 for (int i = 0; i < sz; ++i) { 30 int next = help.front(); help.pop(); 31 int nsz = node[next].size(); 32 for (int t = 0; t < nsz; ++t) { 33 int pnext = node[next][t]; 34 if (vis[pnext] == 1)continue; 35 vis[pnext] = 1; 36 cost[pnext][si] = cnt; 37 help.push(pnext); 38 } 39 } 40 } 41 } 42 43 int main() { 44 int n, m, s, k; 45 scanf("%d %d %d %d", &n, &m, &s, &k); 46 int a0,a1; 47 for (int i = 1; i <= n; ++i) { 48 scanf("%d", &a0); 49 t[a0].push_back(i); 50 } 51 for (int i = 0; i < m; ++i) { 52 scanf("%d %d", &a0, &a1); 53 node[a0].push_back(a1); 54 node[a1].push_back(a0); 55 } 56 for (int i = 1; i <= s; ++i) { 57 memset(vis, 0, sizeof vis); 58 bfs(i); 59 } 60 for (int i = 1; i <= n; ++i) { 61 //排序并选择前k个 62 sort(cost[i] + 1, cost[i] + 1 + s); 63 int sum = 0; 64 for (int t = 1; t <= k; ++t) 65 sum += cost[i][t]; 66 printf("%d ", sum); 67 } 68 }
以上是关于codeforces 987 D. Fair的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #485 (Div. 2) D. Fair
Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path