2019E0_I 治安点

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_44024733/article/details/102752461

治安点

题目

知识点:最短路,最短路的优化

贝克兰德有n个城镇,这些城镇之间有m条道路连接,每条道路有一个长度l。

zf在其中k个城镇设置了治安点。当一个城镇发生事件时,任意一个治安点都可以派人前往。但是为了节省资源,往往会选择距离最近的治安点。

那么请问,对于每一个城镇,最近的治安点距离为多少。

输入

第一行一个整数t表示数据组数(1≤t≤10)

每组数据第一行三个正整数n,m,k (1≤n≤103,n−1≤m≤n∗n/2,1≤k≤n)

第二行k个整数表示治安点所在的位置。

接下来m行,每行三个整数x,y,z,表示x,y之间有一条权值为z的边(无向边) (1≤x,y≤n,1≤z≤10000)

输出

每组数据一行,n个数

输入样例

1
4 7 2 
1 4
1 2 7
1 3 2
1 4 6 
2 1 1
2 4 1
3 2 1
3 4 3

输出样例

0 1 2 0

思路

第一眼看上去是跑k次最短路,优先队列优化的dijkstra算法跑一次复杂度为O(e×log(v))。这样写的话会tle。

那么怎么优化呢?事实上只需要添加k条边,从0到k个选择的点,权值为0,那么事实上只用跑一次即可。省去一维复杂度。

代码

#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <iostream>
#include <map>
#include <random>
#include <queue>
#include <cstring>
using namespace std;
typedef long long ll;
const int ms = 1010;
const int mx = 1000;
int g[ms][ms], point[ms], d[ms], d1[ms];
vector<int> gr[ms];
int n, m, cnt, k;
priority_queue<pair<int, int>>q;
bool vis[ms];

void dij()
{
    memset(d, 0x3f, sizeof(d));
    memset(vis, false, sizeof(vis));

    for (int i = 0; i < k; ++i)
    {
        q.push({ 0,point[i] }); d[point[i]] = 0;
    }
    while (!q.empty())
    {
        int x = q.top().second; q.pop();
        if (vis[x]) continue;
        vis[x] = true;
        for (int i : gr[x])
        {
            int y = i, z = g[x][i];
            if (d[y] > d[x] + z)
            {
                d[y] = d[x] + z;
                q.push({ -d[y],y });
            }
        }
    }
}

int main()
{
    int t = 1;
    scanf("%d", &t);
    while (t--)
    {
        memset(g, 0x3f, sizeof(g));
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 0; i < k; ++i)
        {
            scanf("%d", &point[i]);
        }
        int x, y, z;
        for (int i = 0; i < m; ++i)
        {
            scanf("%d%d%d", &x, &y, &z);
            if (g[x][y] == 0x3f3f3f3f)
            {
                gr[x].push_back(y);
                gr[y].push_back(x);
            }
            g[x][y] = min(g[x][y], z);
            g[y][x] = min(g[y][x], z);
        }
        dij();
        for (int i = 1; i <= n; ++i)
        {
            printf("%d ", d[i]);
            gr[i].clear();
        }
        printf("\n");
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44024733/article/details/102752461