poj 1062

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



原文地址:https://www.cnblogs.com/lj030/p/3002304.html