最短路 P1119 灾后重建【floyd算法】

题目

https://www.luogu.com.cn/problem/P1119

题目分析

题目中要求是查询多个点的最短距离,所以使用Floyd算法实现,而且要真正理解floyd算法的实质

Floyd算法原理

for(k=1;k<=n;k++)

    for(i=1;i<=n;i++)

        for(j=1;j<=n;j++)

            if(e[i][j]>e[i][k]+e[k][j])

                 e[i][j]=e[i][k]+e[k][j];

其实最外层循环就是这个意思:先把1号节点取出来,用内层循环来看1号节点是否能有效缩短i号节点到j号节点的最短距离(i经过1号节点后再到j号节点比i直接到j近)

接着取出2号节点,3号节点……直到将所有的节点全部检验完毕,距离的二维数组中保存的就是各个i节点到j节点的最短路径距离。

题目思路

而题目中的重建时间(从小到大)则正是floyd算法最外层循环的一种隐式的等价,首先查看输入的查询数据中的时间,如果查询时间大于0号城镇的重建时间(题目是从0到n-1),则可以将0号节点取出,看是否能有效缩短i号节点到j号节点的最短距离,接着再比较1号城镇的重建时间与查询数据中的时间大小,一直到某个节点的重建时间比查询数据中的时间大(或者n个节点全部比较完毕),“最外层循环”结束。

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define MAX 210
#define INF 99999999
int edges[MAX][MAX];
int n, m,q;
int t[MAX];
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    cin >> n >> m;
    fill(edges[0], edges[0] + MAX*MAX, INF);
    for (int i = 0; i < n; i++)
        cin >> t[i];
    for (int i = 0; i < m; i++)
    {
        int x, y,z;
        cin >> x >> y>>z;
        edges[x][y] = edges[y][x] = z;
    }
    cin >> q;
    int now = 0;    
    for (int s = 0; s < q; s++)
    {
        int xx, yy, tt;
        cin >> xx >> yy >> tt;
        while (tt >=t[now] && now < n)
        {
                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++)
                        if (edges[i][j] > edges[i][now] + edges[now][j])
                            edges[i][j]=    edges[j][i] = edges[i][now] + edges[now][j];
            now++;
        }
        if (t[xx] > tt || t[yy] > tt)cout << -1 << endl;
        else 
        {
            if (edges[xx][yy] == INF)cout << -1<<endl;
            else cout << edges[xx][yy] << endl;
        }
    }

}

 

posted @ 2020-05-16 09:41  Jason66661010  阅读(160)  评论(0编辑  收藏  举报