题目

做一个替我们首先要明确一下数据范围,n《=200,说明n^3的算法是可以过得,而且这个题很明显是一个图论题, 所以我们很容易想到这个题可以用folyd, 但是我在做这个题的时候因为没有深刻理解folyd的意义,因此导致调试了好几小时,

folyd 的思想是dp,我们可以用洛谷P1119灾后重建表示洛谷P1119灾后重建洛谷P1119灾后重建之间可以通过编号为洛谷P1119灾后重建的节点的最短路径。

初值洛谷P1119灾后重建为原图的邻接矩阵。

洛谷P1119灾后重建可以从洛谷P1119灾后重建转移来,表示洛谷P1119灾后重建洛谷P1119灾后重建不经过洛谷P1119灾后重建这个节点。
也可以从洛谷P1119灾后重建转移过来,表示经过洛谷P1119灾后重建这个点。
意思即洛谷P1119灾后重建

然后你就会发现洛谷P1119灾后重建最外层一维空间可以省略,因为洛谷P1119灾后重建只与洛谷P1119灾后重建有关。

虽然这个算法非常简单,但也需要找点时间理解这个算法,就不会再有这种问题啦。
因此我们在dp循环的时候可以使用滚动数组,可以节约点空间。
这时候我们就可以看回原题了,我们可以先想比较暴力点的算法,就是直接采用floyd,不加任何优化,这样会很慢,因此我们可以寻找可以优化的方法,比如题目中的时间是递增的,因此我们每次状态转移的时候并不用每次都从第一个点找,而是可以接着上一次的询问。
这样题目就一目了然了。
坑点:他的编号都是从0开始的,且初始化数组的时候不能开太大,否则会爆
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#define M 550
using namespace std;
int n, m, dis[M][M], t[M], now, ha, k;
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
        {
            dis[i][j] = 214748364;
        }
    for(int i = 0; i < n; i++)
        scanf("%d", &t[i]);
    for(int i = 1; i <= m; i++)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        dis[a][b] = c;
        dis[b][a] = c;
    }
    scanf("%d", &ha);
    for(int g = 1; g <= ha; g++)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        for(k = now; k < n; k++)
        {
            if(t[k] > c)
                break;
            else
                for(int i = 0; i < n; i++)
                    for(int j = 0; j < n; j++)
                        dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
        }
        now = k++;
        if(dis[a][b] != 214748364 && t[a] <= c && t[b] <= c)
            printf("%d\n", dis[a][b]);
        else
            printf("-1\n");
    }
}

 

相关文章:

  • 2021-08-31
  • 2022-12-23
  • 2021-07-16
  • 2021-12-23
  • 2021-07-19
猜你喜欢
  • 2021-10-14
  • 2021-09-28
  • 2021-07-24
  • 2021-07-10
  • 2021-09-05
相关资源
相似解决方案