AcWing第2周周赛题解
A. AcWing 3626. 三元一次方程
题目链接:https://www.acwing.com/problem/content/3629/
题目大意:求出三元一次方程 \(3x+5y+7z=n\) 的一组非负整数解。
解题思路:枚举 \(x\) 和 \(y\)。
示例程序:
#include <bits/stdc++.h>
using namespace std;
int T, n;
void solve() {
for (int x = 0; 3*x <= n; x++) {
for (int y = 0; 3*x+5*y <= n; y++) {
if ((n - 3*x - 5*y) % 7 == 0) {
int z = (n - 3 * x - 5 * y) / 7;
cout << x << " " << y << " " << z << endl;
return;
}
}
}
cout << -1 << endl;
}
int main() {
cin >> T;
while (T--) {
cin >> n;
solve();
}
return 0;
}
B. AcWing 3627. 最大差值
题目链接:https://www.acwing.com/problem/content/3630/
题目大意:给定一个数列。每次操作选择两个非 0 的元素 ai 和 aj,然后选择一个整数 c(0≤c≤ai),使得 ai 减少 c,aj 增加 c。问,在操作全部完成后,序列中的最大值和最小值之差是多少。
解题思路:贪心。数列中最小的数只能变为 \(0\),每次选择最大的两个数(设为 \(a_i\) 和 \(a_j\))满足 \(a_i \le a_j\),然后将 \(a_i\) 减去 \(a_i\)(变为 \(0\)),将 \(a_j\) 加上 \(a_i\)(变为 \(a_j + a_i\))。具体实现时我准备用优先队列实现。
示例程序:
#include <bits/stdc++.h>
using namespace std;
priority_queue<long long> que;
int T, n, k;
long long a, b;
int main() {
cin >> T;
while (T--) {
while (!que.empty()) que.pop();
cin >> n >> k;
while (n--) {
cin >> a;
que.push(a);
}
while (k--) {
a = que.top();
que.pop();
b = que.top();
que.pop();
que.push(a+b);
}
cout << que.top() << endl;
}
return 0;
}
C. AcWing 3628. 边的删减
题目链接:https://www.acwing.com/problem/content/description/3631/
题目大意:最多保留 \(k\) 条边,使剩下的图中与节点 \(1\) 的最短距离等于之前的图中的最短距离的点的数量尽可能地大,求保留了哪些边。
解题思路:
- 先求最短路(我用的spfa)
- 然后bfs一遍,如果节点 \(1\) 到 \(u\) 的最短路径长度加上 \(u\) 到 \(v\) 的长度等于节点 \(1\) 到 \(v\) 的最短路径长度,则算入这条边,同时 \(v\) 入队。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, m, k;
long long dis[maxn];
bool inq[maxn], ok[maxn], vis[maxn];
queue<int> que;
struct Edge { int v, w, id; };
vector<Edge> g[maxn];
void spfa() {
memset(dis, -1, sizeof(dis));
dis[1] = 0;
que.push(1);
while (!que.empty()) {
int u = que.front(); que.pop(); inq[u] = false;
for (auto e : g[u]) {
int v = e.v, w = e.w;
if (dis[v] == -1 || dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (!inq[v]) {
inq[v] = true;
que.push(v);
}
}
}
}
}
void bfs() {
int cnt = 0; // cnt 表示保留的边的数量
vis[1] = true;
while (!que.empty()) que.pop();
que.push(1);
while (!que.empty() && k > 0) {
int u = que.front();
que.pop();
for (auto e : g[u]) {
int v = e.v, w = e.w;
if (!vis[v] && dis[u] + w == dis[v] && k > 0) {
vis[v] = true;
ok[e.id] = true;
k --;
cnt++;
que.push(v);
}
}
}
cout << cnt << endl;
for (int i = 1; i <= m; i++)
if (ok[i])
cout << i << " ";
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m >> k;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w, i});
g[v].push_back({u, w, i});
}
spfa();
bfs();
return 0;
}