灾后重建(Flody应用)

灾后重建(Flody应用)

P1119 灾后重建
在这里插入图片描述
在这里插入图片描述
思路:

Q访问次数50000如果每次访问都求一次最短路毫无疑问会超时 N <= 200 可以看出Flody算法
巧妙利用条件,每个村庄重建完成时间是单调递增的,访问的时间同是单调递增,每当访问的时间大于当前村庄最大修复时间,即可把小于访问时间的所有村庄作为Flody中转点k,做一次Flody最短路。

样例输入:

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
5
4

代码:

#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 1010, INF = 0x3f3f3f3f;

int g[N][N];
int n, m;
int vg[N];

void flody(int k)
{
	for(int i = 0; i < n; i ++ )
		for(int j = 0; j < n; j ++ )
			g[i][j] = min((LL)g[i][j], (LL)g[i][k] + (LL)g[k][j]);
} 

int main()
{
	scanf("%d %d", &n, &m);
	
	for(int i = 0; i < n; i ++ )
		cin >> vg[i];  //单调递增 
	
	memset(g, 0x3f, sizeof g);
	for(int i = 0; i <= n; i ++ ) g[i][i] = 0; 
	for(int i = 1; i <= m; i ++ )
	{
		int a, b, c;
		cin >> a >> b >> c;
		g[a][b] = g[b][a] = c;
	}
	
	int T;
	cin >> T;
	int now = 0;
	while(T -- )
	{
		int a, b, c;
		cin >> a >> b >> c;  //c单调递增 
		//若当前村庄的修复时间小于now,即作为Flody的中转点更新其他最短路. 
		while(vg[now] <= c && now <= n - 1) flody(now), now ++;
		//若访问的 a - b 的最短路已经更新即可输出 
		if(g[a][b] <= INF / 2 && vg[a] <= c && vg[b] <= c) cout << g[a][b] << endl;
		else cout << -1 << endl;
	}
	
	return 0;
}

 

posted @ 2022-03-25 19:56  panse·  阅读(29)  评论(0)    收藏  举报