一名苦逼的OIer,想成为ACMer

Iowa_Battleship

洛谷1119 灾后重建

原题链接

写了这题才真正知道\(Floyed\)本质。
最原始的\(Floyed\)\(f[k][i][j]\)表示的是以\(i\)为起点,\(j\)为终点,路径上的点的编号不超过\(k\)的最短距离。
所以这题的修复时间恰好就是\(Floyed\)\(k\)这一维的递增转移,边询问边接着跑\(Floyed\)即可。
时间复杂度:\(O(n^3 + Q)\)

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 210;
int dis[N][N], T[N];
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
inline int minn(int x, int y){ return x < y ? x : y; }
int main()
{
	int i, j, k = 1, n, m, x, y, z, t;
	n = re();
	m = re();
	for (i = 1; i <= n; i++)
		T[i] = re();
	memset(dis, 60, sizeof(dis));
	for (i = 1; i <= m; i++)
	{
		x = re() + 1;
		y = re() + 1;
		z = re();
		dis[x][y] = dis[y][x] = z;
	}
	t = re();
	while (t--)
	{
		x = re() + 1;
		y = re() + 1;
		z = re();
		for (; T[k] <= z && k <= n; k++)
			for (i = 1; i <= n; i++)
				if (i ^ k)
					for (j = 1; j <= n; j++)
						if (i ^ j && j ^ k)
							dis[i][j] = dis[j][i] = minn(dis[i][j], dis[i][k] + dis[k][j]);
		dis[x][y] < 1e9 && T[x] <= z && T[y] <= z ? printf("%d\n", dis[x][y]) : printf("-1\n");
	}
	return 0;
}

posted on 2018-11-02 09:26  Iowa_Battleship  阅读(111)  评论(0编辑  收藏  举报

导航