建图方式非常像P1194 买礼物,感觉点权都可以转化到虚拟源点到各个点的边权上。
若不考虑等级关系
- 等价于求虚拟源点到\(1\)号点的最短路。
若考虑等级关系
- 考虑枚举。因为必定和酋长交易,那么整个交换过程可取的就是酋长的等级-m到酋长的等级+m。并且每次交易方案中,最小与最大的等级差不超过m。所以可以枚举酋长等级-m到酋长等级的数做左区间,这个数字加上m做右区间,在跑最短路时判断下是否满足条件,最后取答案最小值即可。
const int N=110;
int val[N],level[N];
vector<PII> g[N];
int dist[N];
bool vis[N];
int n,m;
int dijkstra(int l,int r)//从虚拟源点0到1的最短路
{
memset(dist,0x3f,sizeof dist);
memset(vis,0,sizeof vis);
priority_queue<PII,vector<PII>,greater<PII> > heap;
dist[0]=0;
heap.push({0,0});
while(heap.size())
{
int t=heap.top().second;
heap.pop();
if(vis[t]) continue;
vis[t]=true;
for(int i=0;i<g[t].size();i++)
{
int j=g[t][i].fi,w=g[t][i].se;
if(level[j] > r || level[j] < l) continue;
if(dist[j] > dist[t] + w)
{
dist[j]=dist[t]+w;
heap.push({dist[j],j});
}
}
}
return dist[1];
}
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
int p;
cin>>val[i]>>level[i]>>p;
g[0].push_back({i,val[i]});
while(p--)
{
int x,w;
cin>>x>>w;
g[x].push_back({i,w});
}
}
int res=INF;
for(int i=level[1]-m;i<=level[1];i++)
res=min(res,dijkstra(i,i+m));
cout<<res<<endl;
//system("pause");
}