#include using namespace std; typedef pair 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, greater> 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; }