灾后重建(特长生2016)【Floyed】

>Link

luogu P1119


>解题思路

题意:给出一张有边无点的图,依次激活每一个点,问某些时刻任意两点之间的最短距离
观察到输入数据 n ≤ 200 n≤200 n200,所以考虑用 F l o y e d Floyed Floyed
由于输入的询问天数 t t t为不下降序列,等于我们每次再加入一些点进入图,所以我们不用每次询问都建一个新的图,可以直接在旧图的基础上进行更新
那么如何进行操作?
运用 F l o y e d Floyed Floyed的原理,我们把准备加入的点当做“中转点”再跑一遍 F l o y e d Floyed Floyed就行了,这样可以实现加点操作


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 210
using namespace std;

int n, m, t[N], Q, a[N][N], l;

int main()
{
    
    
	memset (a, -1, sizeof (a));
	scanf ("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) a[i][i] = 0;
	for (int i = 1; i <= n; i++) scanf ("%d", &t[i]);
	int x, y, w;
	for (int i = 1; i <= m; i++)
	{
    
    
		scanf ("%d%d%d", &x, &y, &w);
		x++, y++;
		a[x][y] = a[y][x] = w;
	}
	scanf ("%d", &Q);
	l = 1;
	while (Q--)
	{
    
    
		scanf ("%d%d%d", &x, &y, &w);
		x++, y++;
		while (t[l] <= w && l <= n)
		{
    
    
			for (int i = 1; i <= n; i++)
			  for (int j = 1; j <= n; j++)
			    if (i != j && i != l && j != l)
			      if (a[i][l] != -1 && a[l][j] != -1)
			      {
    
    
			      	if (a[i][j] != -1)
			          a[i][j] = min (a[i][j], a[i][l] + a[l][j]);
			        else a[i][j] = a[i][l] + a[l][j];
				  }
			l++;
		}
		if (t[x] > w || t[y] > w || a[x][y] == -1)
		  printf ("-1\n");
		else printf ("%d\n", a[x][y]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/115030375