POJ 1062 dijkstra + 枚举
这题从下午七点做到晚上的九点半,才做出来。
题意,有一个人A,要去人B那里买东西,人B说了一个价格,然后说如果你能把人C的东西弄来,再加上一部分钱(比直接买人B东西的价格少),也能买到。
于是人A又去了人C那里,人C说了同上的话。依次类推。
但是这个交易圈子里有个规定,就是每个人都有一个等级,如果两个人相差k个等级以上,是不能产生直接或者间接交易的。
问最后你一定要买到人A的东西,最少要多少钱。
分析,分析过后,可以通过交易关系,A需要B的东西,将一条边由B连上A,建立有向图。如果没有等级制度,就是一个裸的dijkstra。存在等级制度加大了题目难度。一个比较简单的处理方法是,如果人A的等级为k,最后存在一条最短路。
那么最短路上的人的权值一定在区间 [k-m,k] [k-m+1,k+1] [k-m+2,k+2] ...... [k,k+m] 这些区间中。枚举区间范围,然后每个范围进行dijkstra,纪录最小答案。
注意细节问题就好。
这题数据很小啊,于是就没有套优先队列优化。
1 /* When all else is lost the future still remains. */
2 /* You can be the greatest */
3 #define rep(X,Y,Z) for(int X=(Y);X<(Z);X++)
4 #define drep(X,Y,Z) for(int X=(Y);X>=(Z);X--)
5 #define fi first
6 #define se second
7 #define mk(X,Y) make_pair((X),(Y))
8 #define inf 0x3f3f3f3f
9 #define clr(X,Y) memset(X,Y,sizeof(X))
10 #define pb push_back
11 //head
12 #include <iostream>
13 #include <stdio.h>
14 #include <queue>
15 #include <algorithm>
16 #include <string>
17 #include <map>
18 #include <string.h>
19 using namespace std;
20 #define maxN 110
21 vector<pair<int,int> > cur[maxN];
22 int val[maxN];
23 int lev[maxN];
24 int dis[maxN];
25 bool mark[maxN];
26 void init(int n){
27 rep(i,0,n+1) cur[i].clear();
28 clr(mark,0);
29 return ;
30 }
31 int find(int n){
32 int ans = -1;
33 int min_val = 2 * inf;
34 rep(i,1,n+1){
35 if(mark[i]) continue;
36 if(dis[i] < min_val){
37 min_val = dis[i];
38 ans = i;
39 }
40 }
41 return ans ;
42 }
43 int dij(int n , int m){
44 int ans = val[1];
45 rep(low,lev[1]-m,lev[1]+1){
46 int p;
47 int high = low + m;
48 rep(i,1,n+1) dis[i] = val[i];
49 clr(mark,0);
50 //
51 while((p = find(n)) != -1){
52 if(mark[1]) break;
53 //printf("%d \n",p);
54 //check(n);
55 mark[p] = 1;
56 if(lev[p] > high || lev[p] < low) continue;
57 int size = cur[p].size();
58 rep(i,0,size){
59 int aim = cur[p][i].fi;
60 int w = cur[p][i].se;
61 if(lev[aim] < low || lev[aim] > high) continue;
62 dis[aim] = min(dis[aim],dis[p] + w);
63 }
64 }
65 ans = min(ans,dis[1]);
66 }
67 return ans;
68 }
69 int main(){
70 int m , n;
71 while(~scanf("%d %d",&m,&n)){
72 init(n);
73 rep(i,1,n+1){
74 int w , l , num;
75 scanf("%d %d %d",&w,&l,&num);
76 val[i] = w; lev[i] = l;
77 rep(j,0,num){
78 int a , b;
79 scanf("%d %d",&a,&b);
80 cur[a].pb(mk(i,b));
81 }
82 }
83 printf("%d\n",dij(n,m));
84 }
85 return 0;
86
87 }