题目大意
- 有n个物品,编号为1…n,每个物品都有三个属性P、L、X(X < N),分别表示物品的价格,等级,替代品数量(即使用其它物品来替代该物品后,只需付出那个物品的价格和替代后的优惠价格即可得到该物品)。
- 给定m,表示物品之间相差等级不能超过m。假设3个物品,m=1,等级依次为1,2,3。可以用2替代1,却不能使用3替代2,因为1,3之间等级超过m。
- 求得到物品1的至少需要付出的金币数量
分析
以物品为节点,可替代的物品之间建单向边(比如可用3替代2,则是一条2指向3的单向边),每条边有一个权值v
v = 起点的价格 - 替换之后的优惠价格 - 终点的价格
- 然后使用dijstra算法求出以节点1开始到各点的最大距离rel即可
- 答案为 P[1] - rel
代码
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
#define INF 0x3fffffff
const int maxn = 110;
struct Edge {
int from , to , v;
Edge() {}
Edge(int x , int y , int z) {from = x; to = y; v = z;}
};
struct HeapNode {
int d , u; //d表示当前节点u距s的距离
HeapNode() {}
HeapNode(int x , int y) {d = x; u = y;}
bool operator < (const HeapNode & rhs) const {
return d < rhs.d;
}
};
vector<Edge> edges;
vector<int> G[maxn]; //G[i][j]表示节点i的第j条边在edges中的编号
int P[maxn] , L[maxn] , X[maxn];
int T[maxn][maxn] , V[maxn][maxn];
void init(int n)
{
edges.clear();
for(int i = 0; i <= n; i++) G[i].clear();
}
void addEdge(int from , int to , int v) {
edges.push_back(Edge(from , to , v));
int m = edges.size();
G[from].push_back(m - 1);
}
int dis[maxn] , vis[maxn] , maL[maxn] , miL[maxn];
int dijstra(int s , int m , int n) //求最长路
{
priority_queue<HeapNode> Q;
for(int i = 0; i <= n; i++) dis[i] = 0;
memset(vis , 0 , sizeof(vis));
Q.push(HeapNode(0 , s));
maL[s] = miL[s] = L[s];
while(!Q.empty())
{
HeapNode cur = Q.top(); Q.pop();
int u = cur.u;
if(vis[u]) continue;
vis[u] = 1;
for(unsigned i = 0; i < G[u].size(); i++) {
Edge &e = edges[G[u][i]];
int tmaL = max(maL[u] , L[e.to]) , tmiL = min(miL[u] , L[e.to]);
if(tmaL - tmiL <= m && dis[e.to] < dis[u] + e.v) {
dis[e.to] = dis[u] + e.v;
//p[e.to] = G[u][i];
maL[e.to] = tmaL , miL[e.to] = tmiL;
Q.push(HeapNode(dis[e.to] , e.to));
}
}
}
int ans = 0;
for(int i = 1; i <= n; i++) ans = max(ans , dis[i]);
return ans;
}
int main()
{
int m , n;
while(cin >> m >> n)
{
init(n);
for(int i = 1; i <= n; i++) {
cin >> P[i] >> L[i] >> X[i];
for(int j = 0; j < X[i]; j++) {
cin >> T[i][j] >> V[i][j];
}
}
for(int i = 1; i <= n; i++) if(L[i] - L[1] <= m) {
for(int j = 0; j < X[i]; j++) {
addEdge(i , T[i][j] , P[i] - V[i][j] - P[T[i][j]]);
}
}
cout << P[1] - dijstra(1 , m , n) << endl;
}
return 0;
}