思路见神犇http://gisyhy.blog.163.com/blog/static/12939034320099883715624/
这题比较麻烦的地方在于等级限制,让我们很不好下手,突破口:1一定在最短路上,所以区间最大为[lev[1]-m,lev[1]+m],但是这样还不满足每两个点的等级之差均在m以内,因此我们枚举[lev[1]-m,lev[1] ],[lev[1]-m+1,lev[1]+1]…[lev[1],lev[1]+m]区间,这些区间内的点一定满足题意,我们用这些点建图,跑spfa。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 105
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int m,n,a[N],d[N],lev[N],h[N],num=0;
bool inq[N];
struct edge{
int to,next,v;
}data[N*N];
int spfa(int s,int t){
memset(d,0x3f,sizeof(d));
queue<int>q;
q.push(1);d[1]=0;inq[1]=1;
while(!q.empty()){
int x=q.front();inq[x]=0;q.pop();
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;
if(lev[y]<s||lev[y]>t) continue;
if(d[x]+data[i].v<d[y]){
d[y]=d[x]+data[i].v;
if(!inq[y]) inq[y]=1,q.push(y);
}
}
}int res=inf;
for(int i=1;i<=n;++i)
res=min(res,d[i]+a[i]);
return res;
}
int main(){
// freopen("a.in","r",stdin);
m=read();n=read();
for(int i=1;i<=n;++i){
a[i]=read();lev[i]=read();int nn=read();
while(nn--){//i->x
int x=read(),v=read();
data[++num].to=x;data[num].next=h[i];h[i]=num;data[num].v=v;
}
}int ans=inf;
for(int i=lev[1]-m;i<=lev[1];++i)//枚举lev区间
ans=min(ans,spfa(i,i+m));
printf("%d\n",ans);
return 0;
}