zoukankan      html  css  js  c++  java
  • codeforces 987 D. Fair

    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 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.

    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 }
  • 相关阅读:
    django 日志窜打问题
    获取f5 应用并发数情况返回JSON
    埋在 MySQL 数据库应用中的17个关键问题!
    python 模拟发送JSON数据
    python 模拟 curx -u
    分区表和全局索引
    Oracle 普通表转分区表
    阿里云吕漫漪:深度解析国内首个云原生数据库POLARDB的“王者荣耀”
    哪些顾虑会影响企业采用云桌面?
    哪些顾虑会影响企业采用云桌面?
  • 原文地址:https://www.cnblogs.com/tobyw/p/9173068.html
Copyright © 2011-2022 走看看