单源最短路径,此题主要是要理解题目的意思。根据“他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。”这句话可知,一定要在一符合要求的区间(这个区间的上限和下限要符合等级限制,并且要包括编号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; }