洛谷:灾后重建
先看数据,显然很小,题目又要回答任意点到任意点的最短路,显然多源汇最短路问题,义眼钉真Floyd
但询问卡死了… 5W一开始直接劝退,没什么很好的头绪。
结果此题只是一道简单的基于Floyd算法本质的签到题
蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡
洛谷第一篇题解就很棒:(婴幼儿都能听懂Orz )
Time_Rune大佬
祖传代码 + 注释:
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul u << 1
#define ur u << 1 | 1
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 210, M = 50010, MM = 100010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S;
int d[N][N];
int ht[N], top = 1;
inline void floyd(int k) {
for (int i = 1; i <= n; i++)
//虽然最外层 k 是可以任意枚举,但内层是不能变的
//必须枚举所有有可能的边,因为 k == 1 时,有可能有 1 到 n 的边
//为了保证时间复杂度,这是必须要更新的,不可以for(1,k),会漏信息
for (int j = 1; j <= n; j++)
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
//bug —— d[i][k], d[g][k] 加号写成逗号了,min没有{}容不下那么多变量
//直接给我淦蒙了,完全没提示bug在哪,卡了半天
// 只有这坨勾吧:
//error C2064: 项不会计算为接受 2 个参数的函数
//message: 查看对正在编译的函数 模板 实例化“const _Ty & std::min<int, int>(const _Ty&, const _Ty&, _Pr) noexcept(<expr>)”的引用
}
int main() {
cinios;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> ht[i];//ht是单调递增,出题人大恩大德
for (int j = 1; j <= n; j++)
if (i != j)d[i][j] = INF;
}
while (m--)
{
int a, b, x;
cin >> a >> b >> x;
a++, b++;
d[a][b] = d[b][a] = min(d[a][b], x);
}
cin >> T;
while (T--)
{
int a, b, x;
cin >> a >> b >> x; //数据保证 T 组 x 也单调递增
a++, b++;
//所以就不需要排序离线了
//随着 x 更新点即可
while (ht[top] <= x && top <= n)floyd(top++);
//而对于当前时刻未修好的但被更新到了的村庄,进行一个简单判定即可
if (ht[a] > x || ht[b] > x || d[a][b] == INF)cout << -1;
else cout << d[a][b];
cout << '\n';
}
return 0;
}```