http://poj.org/problem?id=1062
题意:有100个物品,每个物品有一个价格值,一个地位值,和他可以用别的物品来补差价换。求换到1号物品的最小代价。
意思就是给一个图,支付起点的点权,然后走边权走到1号点,求最小的代价,其中路上经过的地位值的差不能超过题目的限制。
最暴力的做法,枚举地位的差,每次在反图上跑一次Dijkstra就好。这样貌似进行了多余的拷贝。
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
vector<pair<int, int> >G0[105];
vector<pair<int, int> >G[105];
struct Item {
int id;
int st;
int val;
} item[105];
int dis[105];
bool vis[105];
priority_queue<pair<int, int> > pq;
void dijkstra(int s, int n) {
while(!pq.empty())
pq.pop();
for(int i = 1; i <= n; ++i) {
dis[i] = 0x3f3f3f3f;
vis[i] = 0;
}
dis[s] = 0;
pq.push({-dis[s], s});
while(!pq.empty()) {
int u = pq.top().second;
pq.pop();
if(vis[u])
continue;
vis[u] = 1;
for(int i = 0; i < G[u].size(); ++i) {
int v = G[u][i].first, w = G[u][i].second;
if(dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
pq.push({-dis[v], v});
}
}
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int m, n;
scanf("%d%d", &m, &n);
for(int i = 1; i <= n; ++i) {
item[i].id = i;
scanf("%d%d", &item[i].val, &item[i].st);
int x;
scanf("%d", &x);
while(x--) {
int v, w;
scanf("%d%d", &v, &w);
G0[i].push_back({v, w});
}
}
int minval = 0x3f3f3f3f;
for(int cst = item[1].st - m; cst <= item[1].st; ++cst) {
for(int i = 1; i <= n; ++i)
G[i].clear();
int dst = cst + m;
for(int i = 1; i <= n; ++i) {
if(item[i].st >= cst && item[i].st <= dst) {
G[i] = G0[i];
}
}
dijkstra(1, n);
for(int i = 1; i <= n; ++i) {
dis[i] += item[i].val;
if(item[i].st >= cst && item[i].st <= dst)
minval = min(minval, dis[i]);
}
}
printf("%d\n", minval);
}