You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

69 lines
2.4 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
const int M = N * N; // 边数最多有n^2,这是顶天设置此处与传统的题目不一般的M= N<<1此题目没有明确给出边数上限直接认为N^2
const int INF = 0x3f3f3f3f;
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int c) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
int dist[N]; // 单源最短路径
bool st[N]; // 配合Dijkstra用的是否出队过
int L[N]; // 每个节点的等级
int n, m; // n个物品m表示等级差距限制
int dijkstra(int l, int r) {
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
priority_queue<PII, vector<PII>, greater<PII>> q;
// 距离,节点号
q.push({0, 0}); // 超级源点
dist[0] = 0;
while (q.size()) {
auto t = q.top();
q.pop();
int u = t.second;
if (st[u]) continue;
st[u] = true;
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
// 枚举边时,只处理等级在指定范围内
if (L[v] < l || L[v] > r) continue;
if (dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
q.push({dist[v], v});
}
}
}
return dist[1];
}
int main() {
memset(h, -1, sizeof h); // 初始化邻接表
scanf("%d %d", &m, &n); // m:表示地位等级差距限制n:物品的总数
for (int i = 1; i <= n; i++) { // 枚举每个节点
int p, l, cnt; // 价格 等级 替代品数目
scanf("%d%d%d", &p, &L[i], &cnt);
add(0, i, p); // 虚拟源点0, 0获取i号物品需要p这么多的金币
for (int j = 1; j <= cnt; j++) { // 读入物品i的替代品
int u, v; // 替代品的编号 和 优惠价格
scanf("%d%d", &u, &v); // u:替代品编号v:收到替代品后的收费价格
add(u, i, v); // 从替代品向可替代品引一条长度为v的边
}
}
// 预求最小,先设最大
int res = INF;
// 枚举区间范围进行多次求最小路径
for (int i = L[1] - m; i <= L[1]; i++) res = min(res, dijkstra(i, i + m));
// 输出结果
printf("%d\n", res);
return 0;
}