POJ 1062 昂贵的聘礼
这题说实在话就是模版题,可是你要是不知道模版是怎么工作的,有模版也没用,这个题就是个例子。
所以说这个题给了我个教训就是:有了模版也得自己敲,要不然关键时刻是不管用的。
这个题的关键在于:
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; }