1 /*
2 题意: 物主有一个物品,价值为P,地位为L, 以及一系列的替代品Ti和该替代品所对应的"优惠"Vi
3 g[u][i] 表示的是u物品被i物品替换后的优惠价格!(u>0, i>0)
4 g[u][0]表示不用替换该物品的实际价格 !
5 d[0]表示的是第一个物品经过一系列的物品替换之后的最少优惠价格!
6
7 思路:每当我们通过Dijkstra算法得到离源点(1)最近的距离的节点 p的时候(也就是1...pre[p], p)这条
8 路径上的物品互相替换后得到最优价格,我们需要判断是否满足路径上的任意两个节点的地位差的绝对值是否
9 <=m, 如果不是,那么这条路经就废掉了!要从新找最短路!
10 */
11 #include<iostream>
12 #include<cstdio>
13 #include<cstring>
14 #include<algorithm>
15 #define INF 0x3f3f3f3f
16 using namespace std;
17
18 int g[105][105];
19
20 int d[105];
21 int L[105];
22 int vis[105];
23 int pre[106];
24 int m, n;
25 int minP, maxP;
26
27 bool dfs(int p){
28 if(p==1) return true;
29 if(abs(minP-L[pre[p]])>m || abs(maxP-L[pre[p]])>m){
30 g[pre[p]][p]=INF;//这条路径往回走的过程中,如果发现某两个节点的地位差的绝对值>m, 这一条边无效!
31 return false; //注意:不要改变其他路径的存在情况!
32 }
33 if(minP>L[pre[p]]) minP=L[pre[p]];
34 if(maxP<L[pre[p]]) maxP=L[pre[p]];
35 return dfs(pre[p]);
36 }
37
38 void Dijkstra(){
39 memset(d, 0x3f, sizeof(d));
40 memset(vis, 0, sizeof(vis));
41 d[1]=0;
42 vis[1]=1;
43 int root=1;
44 int minLen, p;
45
46 for(int j=1; j<=n; ++j){
47 minLen=INF;
48 for(int i=0; i<=n; ++i){
49 if(g[root][i]){
50 if(!vis[i] && d[i]>d[root]+g[root][i]){
51 d[i]=d[root]+g[root][i];
52 pre[i]=root;
53 }
54 if(!vis[i] && minLen>d[i]){
55 minLen=d[i];
56 p=i;
57 }
58 }
59 }
60 minP=maxP=L[p];
61 if(p && !dfs(p)){//从路径的地步往上走,看一下时候满足条件
62 while(p!=1){
63 d[p]=INF;
64 p=pre[p];
65 }
66 j=0;//从头开始寻找其他的路径!
67 root=1;
68 memset(vis, 0, sizeof(vis));
69 vis[root]=1;
70 continue;
71 }
72 root=p;
73 vis[root]=1;
74 }
75 }
76
77
78 int main(){
79 while(scanf("%d%d", &m, &n)!=EOF){
80 memset(g, 0x3f, sizeof(g));
81 for(int i=1; i<=n; ++i){
82 int p, x;
83 scanf("%d%d%d", &p, &L[i], &x);
84 g[i][0]=p;
85 while(x--){
86 int v, w;
87 scanf("%d%d", &v, &w);
88 g[i][v]=w;
89 }
90 }
91 Dijkstra();
92 printf("%d\n", d[0]);
93 }
94 return 0;
95 }


 


作者:​​胡峻峥