/*
节点是每个物品
边权是物品之间的替换 例如:dist[1] = 10000 = dist[2]+8000 = dist[3] + 5000
同时 对于边的转移有等级要求不得相差超过M,所以我们可以约束等级区间只能在[l,l+M]才能转移
建一个虚拟点源0
把原物品也当作一个节点
则原问题转化为求min(dist[1]) →2→
↑ ↓
4←0→1
↓ ↑
→3→
0->1
0->4->2->1
0->4->3->1
dist[1] = min(dist[1],dist[2]+w[2][1],dist[3]+w[3][1])
dist[2] = min(dist[2],dist[4]+w[4][2])
dist[3] = min(dist[3],dist[4]+w[4][3])
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=110,M=N*N;//边数最多有n^2
typedef pair<int,int> PII;
int h[N],e[M],ne[M],w[M],idx;
int dist[N];
bool st[N];
int level[N];
int n,m;
void add(int a,int b,int c)
{
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx++;
}
int spfa(int l,int r)
{
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
queue<int> q;
q.push(0);
dist[0] = 0;
while(q.size())
{
int ver = q.front();
q.pop();
st[ver]=false;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(l<=level[j] && level[j]<=r && dist[j] > dist[ver]+w[i])
{
dist[j] = dist[ver]+w[i];
q.push(j);
st[j] = true;
}
}
}
return dist[1];
}
int dijkstra(int l,int r)
{
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
priority_queue<PII,vector<PII>,greater<PII>> heap;
heap.push({0,0});
dist[0] = 0;
while(heap.size())
{
auto t = heap.top();
heap.pop();//忘记pop乐...TLE
int d = t.first;
int ver = t.second;
if(st[ver]) continue;
st[ver] = true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(l<=level[j] && level[j]<=r && dist[j] > d+w[i])
{
dist[j] = d+w[i];
heap.push({dist[j],j});
}
}
}
return dist[1];
}
int main(){
memset(h, -1, sizeof h);
cin >> m >> n;//等级限制m
for(int i = 1;i <= n;++i){
int p, l, nums;
cin >> p >> l >> nums;//第i个物品 价格 等级 替代品数目
level[i] = l;
add(0, i, p);//虚拟点源0 换购1的最小价格=dist[1]
//所有替代品 -> 替代对象 dist[1] = dist[2]+w[2][1]
// 2 -> 1
for(int j = 1;j <= nums;++j){
int t, v;
cin >> t >> v;
add(t, i, v);
}
}
int res = 0x3f3f3f3f;
for(int i = level[1]-m;i <= level[1];++i){//滑动限制等级区间从[2,3] ~ [3,4]
// res = min(res,spfa(i, i + m));
res = min(res,dijkstra(i, i + m));
}
cout << res << endl;
return 0;
}
棒