1. 程式人生 > >codeforces 987 D. Fair

codeforces 987 D. Fair

problem byte sca min AD %d 繼續 遍歷 you

D. 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, \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.

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 Input
5 5 4 3
1 2 4 3 2
1 2
2 3
3 4
4 1
4 5
Output
2 2 2 2 3 
Input
7 6 3 2
1 2 3 3 2 2 1
1 2
2 3
3 4
2 5
5 6
6 7
Output
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$$$ 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