题意:中文题。。不解释。。
思路:网上看的,也有不理解的地方,感谢“暴风雪”在群里的讲解,膜拜~
![poj <wbr>1062 <wbr>经典最短路(酋长聘礼) poj <wbr>1062 <wbr>经典最短路(酋长聘礼)](https://i-blog.csdnimg.cn/blog_migrate/e71783f28d8ed519bfbab10813907598.gif)
把物品当作节点建有向图,物品之间的优惠当作权值,假设0为源点,因为酋长不一定是源点,在等级条件的限制下求出到物品1(酋长的允诺)的最短路径。看了看网上的解题报告,感觉等级条件这里弄的挺巧妙的,有待深刻理解,枚举每个物品的等级,把这个物品的等级假设为当前最大等级,然后把一些不需要交易的节点舍去。
#include<iostream>
#define inf 0x7fffffff
using namespace std;
int map[105][105];//i到j的权值,i物品对j的优惠
int dist[105];
int level[105];//此物品的等级
bool vis[105];
int m,n;
int dijkstra()
{
int i,j,k,min;
for(i=1;i<=n;i++)
{
dist[i]=map[0][i];//0个替代品情况下的价格(原价) ,把0设置为源点
}
for(i=1;i<=n;i++)
{
k=0;
min=inf;
for(j=1;j<=n;j++)
{
if(!vis[j]&&dist[j]<min)
{
min=dist[j];
k=j;
}
}
if(k==0) break;
vis[k]=1;
for(j=1;j<=n;j++)
if(!vis[j]&&dist[k]+map[k][j]<dist[j]&&map[k][j]>0)//可能会有负边?
dist[j]=dist[k]+map[k][j];
}
return dist[1];
}
int main()
{
int a,b,k,i,j,t;
scanf("%d%d",&m,&n);
memset(map,inf,sizeof(map));
memset(vis,0,sizeof(vis));
memset(level,0,sizeof(level));
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a,&b,&k);
map[0][i]=a;
level[i]=b;
for(j=0;j<k;j++)
{
scanf("%d",&t);
scanf("%d",&map[t][i]);
}
}
int temp,min,t_lv;
min=inf;
for(i=1;i<=n;i++)//枚举等级
{
t_lv=level[i];//假设这个物品是最高等级
for(j=1;j<=n;j++)
{
if(level[j]>t_lv||t_lv-level[j]>m)//比它大的等级,或者比它小,但是等级差大于m的物品,标记成不处理的.
vis[j]=1;
else
vis[j]=0;
}
temp=dijkstra();
//printf("%d\n",temp);
if(temp<min)
min=temp;//求出枚举最大等级之后的最小费用
}
printf("%d\n",min);
system("pause");
}