luogu解题报告:P1119灾后重建【图论/最短路】
分析
看到此题,第一反应是堆优化dijkstra解决问题,但询问过多会导致TLE。看数据范围:
看Floyd算法代码:
for (int k = 1; k <= n; k++)
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            dis[i][j] = dis[j][i] = min(dis[i][j], dis[i][k] + dis[k][j]);事实上,Floyd算法是基于动态规划的。根据《算法导论》设
目标为:
而我们通常所见到的Floyd算法则使用了类似滚动数组的思想,因此k需要放到最外层循环。
既然k表示的是以前k个村庄为中转点的最短路径,而题目中被损坏的村庄根据修复先后排了序,询问也按照时间先后拍排了序,那么不难想到,在做Floyd的过程中,可以先进行一个判断:如果当前的k被修复的时间已经超出了询问给定的时间(即前k-1个村庄被修复恰好是该询问所需的情况),且两个顶点也被修复了,那么
实例代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int g[205][205], n, m;
int t[205];
int from[50005], to[50005], timen[50005];
int main()
{
    cin >> n >> m;
    memset(g, 127/3, sizeof g);
    for (int i = 1; i <= n; i++) {
        g[i][i] = 0;
        cin >> t[i];
    }
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        a++; b++;
        g[a][b] = g[b][a] = c;
    }
    int q;
    cin >> q;
    for (int i = 1; i <= q; i++) {
        cin >> from[i] >> to[i] >> timen[i];
        from[i]++; to[i]++;
    }
    int ln = 1;
    for (int k = 1; k <= n; k++) {
        for (; ln <= q && timen[ln] < t[k]; ln++) {
            if (t[from[ln]] >= t[k] || t[to[ln]] >= t[k]
            || g[from[ln]][to[ln]] >= 233333333)
                cout << -1 << endl;
            else
                cout << g[from[ln]][to[ln]] << endl;
        }
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                g[i][j] = g[j][i] = min(g[i][j], g[i][k]+g[k][j]);
    }
    for (; ln <= q; ln++) {
        if (g[from[ln]][to[ln]] >= 233333333)
            cout << -1 << endl;
        else
            cout << g[from[ln]][to[ln]] << endl;
    }
    return 0;
} 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号