Asia EC Online 2025(I) I. Knapsack Problem
题目链接1:Knapsack Problem - Problem - QOJ.ac
题目链接2:The 2025 ICPC Asia East Continent Online Contest (I) - Virtual Judge
题目大意:
n 个顶点和 m 条边的无向图 , 有容量大小为 V 的背包,出发点为 st,(1 <= n,m,V <=1e5)
从 st 点出发,每经过一个点,就要把这个点重量为 w[i] 的一个物品带上,
如果放不下,就只能把这个背包丢掉,用一个新的背包装填,(不能分割物品,数据w[i] < V)
求:从 st 点出发,到每个点最小使用的背包数量,若不能到达输出 -1 ;
Dijkstra:
从大意来看,是要走一遍最短路,
从数据来看,如果用普通的 Dijkstra 必然超时,
因此我们只能使用 堆优化Dijkstra(时间复杂度nlogn),
从贪心的角度看,每走到下一个点,我们希望使用的背包最小,即使背包数不能再小,我们也希望当前背包的容量尽可能大
那堆的排序 应该是 在使用的背包数尽可能少的前提下让当前背包的剩余容量大
然后跑一边 Dijkstra
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<bitset>
#include<tuple>
#define inf 72340172838076673
#define int long long
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
using namespace std;
typedef pair<int, int> pii;
const int N = 200086, mod = 998244353;
int n, m, x, st;
int h[N], ne[N], e[N], w[N], idx;
bool v[N];
struct node {
int d, u, has;//使用的背包次数,节点,剩余的空间
bool operator<(const node &b)const {
if (d == b.d) return has < b.has;
return d > b.d;
}
};
priority_queue <node> q;
int dis[N], sheng[N];
void add(int a, int b, int c) {
w[idx] = c;
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dij() {
mst(dis, 1);
q.push({1, st, x});
dis[st] = 1, sheng[st] = x;
while (q.size()) {
auto[d, u, has] = q.top();
q.pop();
if (v[u]) continue;
v[u] = true;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
int dd = d, hh = has - w[i];
if (hh < 0) {
dd++;//背包次数+1
hh = x - w[i];//用新背包放下该物品之后剩余的容量
}
//如果 当前背包数更小 或 背包书相等 同时 剩下的容量更多
if (dd < dis[j] || (dis[j] == dd && hh > sheng[j])) {
dis[j] = dd;
sheng[j] = hh;
q.push({dd, j, hh});
}
}
}
}
void solve() {
mst(h, -1);
cin >> n >> m >> x >> st;
for (int i = 1; i <= m; i++) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
add(b, a, c);
}
dij();
for (int i = 1; i <= n; i++) {
if (dis[i] > inf / 2) cout << "-1" << " ";
else cout << dis[i] << " ";
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}

浙公网安备 33010602011771号