题解:
-
如果a可以代替b,那么就连一条从a到b的边,权值为用b代替a,a需要的价格。
-
再加一个点n+1,n+1连接所有点,权值为旅行家直接花钱的价格
-
最后求的便是从n+1到1的最短路,并且路上结点的权值差绝对值小于等于M
-
一开始我是记录路径,保存以前路上的等级最大值和最小值,但是行不通。后来参考了百度,原来可以枚举区间。枚举的区间必须包括酋长,设酋长等级为level,则区间为[level-M,level+M],但是还不行,因为中间可能会有等级差大于M,所以区间枚举为[level-M,level],[level-M+1,level+1]……[level,level+M]。然后Dijkstra。
代码:
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;
int const inf = 0x7f7f7f7f;
int const N = 100 + 10;
int m,n,w[N],dis[N];
struct Edge
{
int to,dist;
};
vector<Edge>G[N];
void Init(){
for(int i=1;i<=n+1;i++) G[i].clear();
for(int i=1;i<=n;i++){
int p,l,x;
scanf("%d%d%d",&p,&l,&x);
w[i] = l;
G[n+1].push_back((Edge){i,p});
for(int j=0;j<x;j++){
int t,v;
scanf("%d%d",&t,&v);
G[t].push_back((Edge){i,v});
}
}
}
struct Node
{
int u,len;
Node(){};
Node(int uu,int le):u(uu),len(le){};
bool operator < (const Node &e) const{
return len < e.len;
}
};
priority_queue<Node>q;
void Dijkstra(int l,int r){
for(int i=0;i<=n+1;i++) dis[i] = inf;
dis[n+1] = 0;
q.push(Node(n+1,0));
while(!q.empty()){
Node p = q.top(); q.pop();
int u = p.u, len = p.len;
if(dis[u] < len) continue;
for(int i=0;i<G[u].size();i++){
Edge e = G[u][i];
if(l <= w[e.to] && w[e.to] <= r){
if(dis[e.to] > dis[u] + e.dist){
dis[e.to] = dis[u] + e.dist;
q.push(Node(e.to,dis[e.to]));
}
}
}
}
}
int main(){
while(~scanf("%d%d",&m,&n)){
Init();
int ans = inf;
for(int i=w[1]-m;i<=w[1];i++){
Dijkstra(i,i+m);
ans = min(ans,dis[1]);
}
printf("%d\n",ans);
}
}