这题说实在话就是模版题,可是你要是不知道模版是怎么工作的,有模版也没用,这个题就是个例子。
所以说这个题给了我个教训就是:有了模版也得自己敲,要不然关键时刻是不管用的。
这个题的关键在于:
1、虚拟一个节点0,所有物品的价值被表示为这个点到对应物品编号点的边的权值。
2、相关联的物品连一条权为优惠价格的边。
3、求节点0与节点1之间的最短路就行了。
要注意的的是:
1、酋长不一定是最高级,所以控制交易等级范围时不一定酋长是等级上界,需要对等级范围进行枚举。
2、交易等级范围就是等级差的大小,因为间接交易超过等级差也不行。
下面是代码:
#include <stdio.h>
const int V=105;
const int E=10005;
struct node
{
int mon,lv;
} wu[V];
struct node1
{
int u,v,w;
} edge[E];
int m,l,r,dis[V],vis[V];
void bellmam_ford(int n)
{
int i,j,flat;
for(i=0; i<n; i++)//初始化0点到各点的权值,及各物品的价值,dis[0]=0。
{
dis[i]=wu[i].mon;
}
flat=0;
for(i=1; i<=n; i++)
{
for(j=0; j<m; j++)
{
if(wu[edge[j].u].lv>=l&&wu[edge[j].u].lv<=r&&wu[edge[j].v].lv>=l&&wu[edge[j].v].lv<=r&&dis[edge[j].u]>dis[edge[j].v]+edge[j].w)
{
dis[edge[j].u]=dis[edge[j].v]+edge[j].w;
flat=1;
}
}
if(!flat)
{
break;
}
}
}
int main()
{
int M,N;
while(scanf("%d%d",&M,&N)!=EOF)
{
int i,j,t;
m=0;
for(i=1; i<=N; i++)//进行输入,建立有向边的邻接表。
{
scanf("%d%d%d",&wu[i].mon,&wu[i].lv,&t);
edge[m].u=0;
edge[m].v=i;
edge[m].w=wu[i].mon;
m++;
for(j=0; j<t; j++)
{
scanf("%d%d",&edge[m].v,&edge[m].w);
edge[m].u=i;
m++;
}
}
int min1=wu[1].mon;
wu[0].lv=wu[1].lv;
for(l=wu[1].lv-M; l<=wu[1].lv; l++)//枚举等级范围,范围长度为M。
{
r=l+M;
bellmam_ford(N+1);//因为多虚拟一个点,所以是n+1个点
if(min1>dis[1])
{
min1=dis[1];
}
}
printf("%d\n",min1);
}
return 0;
}