POJ-1062 昂贵的聘礼---Dijkstra+枚举上界
题目链接:
https://vjudge.net/problem/POJ-1062
题目大意:
中文题
思路:
1是终点,可以额外添加一个源点0,0到任意一节点的距离就是这个点的money,最终求的是d[1]最小值,但是由于有等级观念,所以必须枚举,每次枚举等级的上界,如果有不符合当前枚举的上界,就标记其不加入dijk算法中,然后跑一遍最短路,求出d[1],最终取d[1]的最小值
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<set> 10 #include<sstream> 11 #define MEM(a, b) memset(a, b, sizeof(a)); 12 using namespace std; 13 typedef long long ll; 14 const int maxn = 100 + 10; 15 const int INF = 0x3f3f3f3f; 16 int T, n, m, cases;//m是等级差 17 int Map[maxn][maxn]; 18 int d[maxn], v[maxn]; 19 struct node 20 { 21 int money, rank; 22 }cnt[maxn]; 23 int dijkstra() 24 { 25 for(int i = 1; i <= n; i++)d[i] = cnt[i].money;//假定的原点0,到每个点的距离就是它自己的价格 26 for(int i = 1; i <= n; i++) 27 { 28 int x = 0, m = INF; 29 for(int i = 1; i <= n; i++)if(!v[i] && m > d[i])m = d[x = i];//找出当前在集合中的最小距离 30 if(!x)break;//已经全部标记完毕 31 v[x] = 1; 32 for(int i = 1; i <= n; i++) 33 if(!v[i])d[i] = min(d[i], d[x] + Map[x][i]);//这里必须加上判断条件,因为有部分物品由于等级限制没有加入选项中 34 } 35 return d[1]; 36 } 37 int main() 38 { 39 cin >> m >> n; 40 for(int i = 1; i <= n; i++) 41 for(int j = 1; j <= n; j++)Map[i][j] = INF; 42 MEM(cnt, 0); 43 MEM(v, 0); 44 int x, a, b; 45 for(int i = 1; i <= n; i++) 46 { 47 cin >> cnt[i].money >> cnt[i].rank >> x; 48 while(x--) 49 { 50 cin >> a >> b; 51 Map[a][i] = b;//存图,存下从a到i的路径,这样就可以转化成求到点1的最短路径 52 } 53 } 54 int ans = INF; 55 for(int i = 1; i <= n; i++) 56 { 57 int maxrank = cnt[i].rank;//枚举rank的上界 58 for(int j = 1; j <= n; j++) 59 if(maxrank - cnt[j].rank > m || cnt[j].rank > maxrank)v[j] = 1; 60 //事先标记好不符合条件的物品,如果有等级大于当前枚举的最大等级或者等级差超过m的标记,在dijk算法中不添加这些元素 61 else v[j] = 0; 62 ans = min(ans, dijkstra()); 63 } 64 cout<<ans<<endl; 65 return 0; 66 }
越努力,越幸运