dijstra+枚举法,,,
题意中文不再说明了,,,,,
解法:求一点到其他所有点的最短路径(还要加上终点的pri[]),在一条路径上点与点之间的等级差不能超过n,
扫描区间因为每条路径都要经过点1,所以依次扫描区间[ lev[1]-n , leve[1] ]......[ lev[1] , lev[1]+n ]
代码:
#include<iostream>
#include<algorithm>
#include<string.h>
#define N 1001
#define M 111111111
using namespace std;
int map[N][N],G[N][N],dis[N],lev[N],pre[N];
int n,m,k;
bool visit[N];
void dijstra(int a)
{ memset(visit,false,sizeof(visit));
for(int i=1;i<=m;++i) dis[i]=(a==i?0:M);
for(int i=1;i<=m;++i)
{ int minx=M;
for(int j=1;j<=m;++j)
if(!visit[j]&&minx>dis[j])
minx=dis[a=j];
visit[a]=true;
for(int j=1;j<=m;++j)
if(!visit[j])
dis[j]=min(dis[j],dis[a]+map[a][j]);
}
}
void sift(int l,int r)//扫描两端的等级不在1-r上的把它赋为M。
{ for(int i=1;i<=m;++i)
for(int j=1;j<=m;++j)
if(lev[i]>=l&&lev[i]<=r&&lev[j]>=l&&lev[j]<=r) map[i][j]=G[i][j];
else map[i][j]=M;
}
int pro()
{ int minx=M;
for(int i=lev[1]-n;i<=lev[1];++i)
{ sift(i,i+n);//依次扫描。
dijstra(1);
for(int j=1;j<=m;++j)
minx=min(minx,dis[j]+pre[j]);
}
return minx;
}
int main()
{ cin>>n>>m;
for(int i=0;i<=m;i++)
for(int j=0;j<=m;j++)
{
G[i][j]=M;
map[i][j]=M;
}
for(int i=1;i<=m;++i)
{ cin>>pre[i]>>lev[i]>>k;
for(int j=1;j<=k;++j)
{ int a,b;
cin>>a>>b;
G[i][a]=b;
}
}
cout<<pro()<<endl;
return 0;
//system("pause");
}