给个图,有边权和点权,多组询问只能经过点权小于等于K的点的 两点之间的最短距离

先将点按照点权排序,从小到大枚举每个点作为中间的点,跑 floyd ,询问只需要找到最大的小于等于K的点权的那层图,直接输出就可以。

https://nanti.jisuanke.com/t/41290

#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
#define Pair pair<int,int>
Pair a[100000];
ll dp[205][205][205];
int b[205];
int n, q;
void Flody()
{
	for (int k = 1; k <= n; k++)
	{
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				dp[k][i][j] = min(dp[k - 1][i][j], dp[k - 1][i][a[k].first] + dp[k - 1][a[k].first][j]);
			}
		}
	}
}
int main()
{
	int T, cas = 1;
	sc("%d", &T);
	while (T--)
	{
		pr("Case #%d:\n", cas++);
		sc("%d%d", &n, &q);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				for (int k = 1; k <= n; k++)
					dp[i][j][k] = 1e9 + 7;
		for (int i = 1; i <= n; i++)
		{
			a[i].first = i;
			sc("%d", &a[i].second);
		}
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				sc("%d", &dp[0][i][j]);
		sort(a + 1, a + n + 1, [](Pair q, Pair w) {
			return q.second < w.second;
		});
		for (int i = 1; i <= n; i++)
			b[i] = a[i].second;
		Flody();
		while (q--)
		{
			int u, v, k;
			sc("%d%d%d", &u, &v, &k);
			k = upper_bound(b + 1, b + 1 + n, k) - b - 1;
			pr("%lld\n", dp[k][u][v]);
		}
	}
}