P1119 floyd

最开始看错数据了没看到Q = 100 是50%的数据以为跑q遍floyd能过,结果只有30,其他全t

1、要注意题目中的条件,挖掘一些性质

2、本题的另一个关键的是要对floyd的过程原理比较熟悉,floyd一共有三重循环,第一重循环相当于枚举的决策,也就是能从那个点转移过来,k就是这个中转站,另外两重循环是枚举的状态

3、我们观察到每个村庄的重建时间是递增的,并且询问的时间也是递增或保持不变,所以我们可以在读入每个询问的时间时,看一下是否存在中转站,在这个时间已经建好,并且可以去更新其他点,我们找到所以这样的点去更新,然后cur不用回去,因为询问的时间也是递增的,只需要在读入下一个询问后,查看是否有新的中转点可以去更新其他点即可。

4、经过上面的分析我们可以知道我们只需要跑一遍floyd即可,因为只有满足的中转点才会被用,时间复杂度为O(n^3)

附上floyd的板子

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 210, INF = 1e9;

int n, m, Q;

int d[N][N];

void Floyd()
{
    for(int k = 1; k <= n; k ++)
        for(int i = 1; i <= n; i ++)
         for(int j = 1; j <= n; j ++)
            //要取一下最小值这个写的时候老是忘记
            d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}

int main()
{
    cin >> n >> m >> Q;
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            if(i == j)  d[i][j] = 0;
            else    d[i][j] = INF;

    for(int i = 0; i < m; i ++)
    {
        int a, b, w; cin >> a >> b >> w;
        d[a][b] = min(d[a][b], w);
     }

    Floyd();

    while(Q --)
    {
        int a, b; cin >> a >> b;
        if(d[a][b] > INF / 2)   puts("impossible");
        else    cout << d[a][b]<<endl;;
    }

    return 0;
}

灾后重建

题目背景

B 地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。

题目描述

给出 B 地区的村庄数 N,村庄编号从 0N1,和所有 M 条公路的长度,公路是双向的。并给出第 i 个村庄重建完成的时间 ti,你可以认为是同时开始重建并在第 ti 天重建完成,并且在当天即可通车。若 ti0 则说明地震未对此地区造成损坏,一开始就可以通车。之后有 Q 个询问 (x,y,t),对于每个询问你要回答在第 t 天,从村庄 x 到村庄 y 的最短路径长度为多少。如果无法找到从 x 村庄到 y 村庄的路径,经过若干个已重建完成的村庄,或者村庄 x 或村庄 y 在第 t 天仍未重建完成,则需要返回 -1

输入格式

第一行包含两个正整数N,M,表示了村庄的数目与公路的数量。

第二行包含N个非负整数t0,t1,,tN1,表示了每个村庄重建完成的时间,数据保证了t0t1tN1

接下来M行,每行3个非负整数i,j,ww为不超过10000的正整数,表示了有一条连接村庄i与村庄j的道路,长度为w,保证ij,且对于任意一对村庄只会存在一条道路。

接下来一行也就是M+3行包含一个正整数Q,表示Q个询问。

接下来Q行,每行3个非负整数x,y,t,询问在第t天,从村庄x到村庄y的最短路径长度为多少,数据保证了t是不下降的。

输出格式

Q行,对每一个询问(x,y,t)输出对应的答案,即在第t天,从村庄x到村庄y的最短路径长度为多少。如果在第t天无法找到从x村庄到y村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄y在第t天仍未修复完成,则输出1

样例 #1

样例输入 #1

4 5
1 2 3 4
0 2 1
2 3 1
3 1 2
2 1 4
0 3 5
4
2 0 2
0 1 2
0 1 3
0 1 4

样例输出 #1

-1
-1
5
4

提示

对于30%的数据,有N50

对于30%的数据,有ti=0,其中有20%的数据有ti=0N>50

对于50%的数据,有Q100

对于100%的数据,有N200MN×(N1)/2Q50000,所有输入数据涉及整数均不超过100000

#include <iostream>
#include <cstring>
using namespace std;
const int N = 210, INF = 2e9;

long long  d[N][N], a[N];
bool st[N];
int n, m;

inline void floyd(int k)
{
    for(int i = 0; i < n; ++ i)
        for(int j = 0; j < n; ++ j)
        if(d[i][j] > d[i][k] + d[k][j]) 
            d[i][j] = d[i][k] + d[k][j];
            
}

int main()
{   
    // freopen("1.in.txt", "r", stdin);
    cin >> n >> m;
    for(int i = 0; i < n; ++ i) cin >> a[i];
    for(int i = 0; i < n; ++ i)
        for(int j = 0; j < n; ++ j)
        {
            if(i == j)  d[i][i] = 0;
            d[i][j] = INF;
        }
            
    for(int k = 0; k < m; ++ k)
    {
        int a, b ,c; cin >> a >> b >> c;
        d[a][b] = d[b][a] = c;
    }
 
    int q, cur = 0;cin >> q;
    while(q --)
    {
        int x, y, t; cin >> x >> y >> t;
        while(a[cur] <= t && cur < n) 
        {
            floyd(cur);
            cur ++;
        }
        if(a[x] > t || a[y] > t || d[x][y] == INF)  cout << -1 << endl;
        else    cout << d[x][y] << endl;
    }
    return 0;
}
posted @   cxy8  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
点击右上角即可分享
微信分享提示