poj1062昂贵的聘礼
思路: 首先不考虑等级限制。
建图:
对于每个物品,我们将其作为一个点,将其代替品以其代替品价格为边权建边指向这个点,一直指到第一个物品,在这个过程中,我们还需要建立一个超级源点来指向每个物品代表其自身的价格。
其次考虑等级限制
对于每一个物品,要想他可以进行购买,其等级必须在 l e v e l [ 1 ] − m level[1]-m level[1]−m~ l e v e l [ 1 ] + m level[1]+m level[1]+m之间,所以,我们只需要依次遍历这个区间在满足这个区间上跑dijkstra,依次对所有节点进行更新取最小值即可。
在进行朴素迪杰斯特拉算法时,需要注意的是要从0点开始寻找未被遍历的点。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<sstream>
#include<queue>
#define pi 3.1415926535
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e6 + 10;
int h[N], e[N], ne[N], idx, w[N];
void add(int a, int b, int c) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
int n, m;
int level[N];
int g[110][110];
int dis[N];
bool st[N];
int dijkstra(int up, int down) {
memset(dis, 0x3f, sizeof dis);
memset(st, false, sizeof st);
dis[0] = 0;
for (int i = 1; i <= n; i++) {
int t = -1;
for (int j = 0; j <= n; j++)//注意从0开始
if (!st[j] && (t == -1 || dis[t] > dis[j]))
t = j;
st[t] = true;
for (int j = 1; j <= n; j++) {
if (level[j] >= up && level[j] <= down) {
dis[j] = min(dis[j], dis[t] + g[t][j]);
}
}
}
return dis[1];
}
int main() {
cin >> m >> n;
memset(g, 0x3f, sizeof g);
for (int i = 1; i <= n; i++)g[i][i] = 0;
for (int i = 1; i <= n; i++) {
int price, cnt;
cin >> price >> level[i] >> cnt;
g[0][i] = min(g[0][i], price);
while (cnt--)
{
int id, cost;
cin >> id >> cost;
g[id][i] = min(g[id][i], cost);
}
}
int ans = 0x3f3f3f3f;
for (int i = level[1] - m; i <= level[1]; i++) ans = min(ans, dijkstra(i, i + m));
cout << ans << endl;
}