单源最短路径,此题主要是要理解题目的意思。根据“他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。”这句话可知,一定要在一符合要求的区间(这个区间的上限和下限要符合等级限制,并且要包括编号1)里找,然后把所有符合要求的区间的值进行比较,从而得到在限制条件下的最短路径
#include <iostream>
using namespace std;
#define maxn 201
#define INF 2<<20
int edge[maxn][maxn];
int inlim[maxn],lev[maxn],val[maxn];
int n,m;
int dijkstra()//求当前等级区间中的最小消费
{
int i,j;
int lc[maxn],vis[maxn];
for(i=2;i<=n;i++)
{
lc[i]=edge[1][i];
vis[i]=0;
}
vis[1]=1,lc[1]=0;
int mc,k;
for(i=1;i<n;i++)
{
mc=INF;//因为这个地方debug了两个多小时
k=1;
for(j=2;j<=n;j++)
{
if(inlim[j]&&!vis[j]&&lc[j]<=mc)
{
mc=lc[j];
k=j;
}
}
vis[k]=1;
for(j=2;j<=n;j++)
{
if(inlim[j]&&!vis[j]&&lc[j]>lc[k]+edge[k][j])
lc[j]=lc[k]+edge[k][j];
}
}
int tot=INF;
for(i=1;i<=n;i++)
{
if(inlim[i])//任何操作都是在选定区间中进行,也就是说其他的点就当不存在一样
{
lc[i]+=val[i];//编号1到各点的最短路径还得加上买它本身所用的价钱,这样才能判断哪个路径消费最少
if(lc[i]<tot) tot=lc[i];
}
}
return tot;
}
int main()
{
while(cin>>m>>n)
{
int i,t,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
edge[i][j]=i==j?0:INF;
}
}
int ta,tv;
for(i=1;i<=n;i++)
{
cin>>val[i]>>lev[i]>>t;
for(j=0;j<t;j++)
{
cin>>ta>>tv;
edge[i][ta]=tv;
}
}
int bas=lev[1];
int mc=INF,tc;
for(i=0;i<=m;i++)
{
memset(inlim,0,sizeof(inlim));
for(j=1;j<=n;j++)//每次选定一个满足“但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样”的区间
{
if((lev[j]>=(bas-i))&&(lev[j]<=(bas-i+m)))
inlim[j]=1;
}
tc=dijkstra();
if(tc<mc) mc=tc;
}
cout<<mc<<endl;
}
return 0;
}