专栏文章

题解:P12332 [蓝桥杯 2023 省 Java B] 魔法阵

P12332题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mink8sfa
此快照首次捕获于
2025/12/02 03:46
3 个月前
此快照最后确认于
2025/12/02 03:46
3 个月前
查看原文

题目传送门

观察到 kk 极小,所以你直接考虑对原图建分层图。考虑再分层图上的两种转移(设层数 i[0,k]i\in [0,k]):
  1. 这条边没选,需要满足 i=0i=0i=ki=k,那么直接在第 ii 层图转移。转移时边权按原边权算。
  2. 这条边选了,需要满足 i<ki<k,那么从第 ii 层图转移到第 i+1i+1 层图,转移时边权按 00 算。
答案即为 min(fn1,0,fn1,k)\min(f_{n-1,0},f_{n-1,k})
实际上只需要在松弛更新的时候考虑这两种转移即可,根本不需要把分层图建出来。直接硬跑 dij 或 已死算法spfa 都能过。
CPP
#include <bits/stdc++.h>
using namespace std;
#define il inline
#define mkp make_pair
#define pi pair<int, int>
typedef long long ll;
const int N = 1e3 + 10, K = 11;
int f[N][K], inf = 1e9, n, m, k;
queue<pi> q;
vector<pi> g[N];
bool inque[N][K];
il void spfa(int s)
{
	for(int i = 0;i < n;++i)
		for(int j = 0;j <= k;++j)
			f[i][j] = inf;
	f[s][0] = 0;
	inque[s][0] = 1;
	q.push(mkp(s, 0));
	while(q.size())
	{
		pi cur = q.front();
		q.pop();
		int u = cur.first, j = cur.second;
		inque[u][j] = 0;
		for(auto vv : g[u])
		{
			int v = vv.first, w = vv.second;
			if((j == 0 || j == k) && f[v][j] > f[u][j] + w)
			{
				f[v][j] = f[u][j] + w;
				if(!inque[v][j])
				{
					q.push(mkp(v, j));
					inque[v][j] = 1;
				}
			}
			if(j < k && f[v][j + 1] > f[u][j])
			{
				f[v][j + 1] = f[u][j];
				if(!inque[v][j + 1])
				{
					q.push(mkp(v, j + 1));
					inque[v][j + 1] = 1;
				}
			}
		}
	}
}
int main()
{
	cin >> n >> k >> m;
	while(m--)
	{
		int u, v, w;
		cin >> u >> v >> w;
		g[u].push_back(mkp(v, w));
		g[v].push_back(mkp(u, w));
	}
	spfa(0);
	cout << min(f[n - 1][0], f[n - 1][k]);
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...