昂贵的聘礼,(最短路的应用),Poj(1063)
题目链接:http://poj.org/problem?id=1062
很好的一道中文题。
思路:
把每种替换当做一条边,权重为交易优惠,就是求原点0到物品1的最短路。
这里有限制条件,每个节点还有等级,一条路中任意两个点之间的等级小于li.这里,我只要枚举每个点,以它为标准,删掉那些等级差大于li的点,再进行dijkstra就行了。
#include <stdio.h> #include <string.h> #include <algorithm> #define NUM 1005 #define maxint (1<<29) using namespace std; int li,n; int c[NUM][NUM]; int dist[NUM]; int pre[NUM]; int vis[NUM]; int x[NUM]; int lv[NUM]; void dijkstra() { for(int i=1;i<=n;i++) dist[i] = c[0][i]; for(int i=1;i<=n;i++) { int u = 0; int minl = maxint; for(int j=1;j<=n;j++) { if(minl>dist[j]&&!vis[j]) { u = j; minl = dist[j]; } } if(u == 0) break; vis[u] = true; for(int j=1;j<=n;j++) { if(!vis[j]&&c[u][j]>0&&dist[j]>dist[u]+c[u][j]) dist[j] = dist[u]+c[u][j]; } } } int main() { memset(c,0,sizeof(c)); memset(lv,0,sizeof(lv)); memset(dist,maxint,sizeof(dist)); memset(vis,false,sizeof(vis)); scanf("%d%d",&li,&n); for(int i=1;i<=n;i++) { scanf("%d%d%d",&c[0][i],&lv[i],&x[i]); for(int j=1;j<=x[i];j++) { int t,u; scanf("%d%d",&t,&u); c[t][i] = u; ///替代品到物品i } } int tmp; int minprice = maxint; for(int i=1;i<=n;i++) { int maxlv = lv[i]; for(int j=1;j<=n;j++) { if(lv[j]>maxlv||maxlv-lv[j]>li) vis[j] = true; else vis[j] = false; } dijkstra(); tmp = dist[1]; if(tmp<minprice) minprice = tmp; } printf("%d\n",minprice); return 0; }