C++ 算法竞赛、02 周赛篇 | AcWing 第2场周赛
阅读原文时间:2023年09月07日阅读:1

AcWing 第2场周赛

竞赛 - AcWing

AcWing 3626. 三元一次方程 - AcWing

两层循环

#include <iostream>

using namespace std;

void find(int n) {
    for (int x = 0; x <= 1000 / 3; x++) {
        for (int y = 0; y <= 1000 / 5; y++) {
            int res = n - 3 * x - 5 * y;
            if (res < 0) {
                continue;
            } else if (res % 7 == 0) {
                cout << x << " " << y << " " << res / 7 << endl;
                return;
            }
        }
    }
    cout << "-1" << endl;
}

int main() {
    int m;
    cin >> m;
    while (m--) {
        int n;
        cin >> n;
        if (n < 0) {
            cout << "-1" << endl;
            continue;
        }
        find(n);
    }
}

3627. 最大差值 - AcWing题库

考查贪心,所有输入的不是0的数排序,每次操作取最大的数++,由于每个数最大可以是1e9,int可能溢出,需要用 long long

#include <algorithm>
#include <iostream>

using namespace std;

const int N = 2e5 + 10;

int t, n, k;
int a[N];
int main() {
    cin >> t;
    while (t--) {
        cin >> n >> k;
        int idx = 0;
        for (int i = 0; i < n; i++) {
            int x;
            scanf("%d", &x);
            if (x != 0) a[idx++] = x;
        }
        sort(a, a + idx);
        long long res = a[--idx];
        int i = idx - 1;
        while (k--)
            if (i >= 0) res += a[i--];
        cout << res << endl;
    }
}

3628. 边的删减 - AcWing题库

刚开始有点傻,打算用克鲁斯卡尔生成最小生成树,题意明显不是这样的

  • 最小生成树能够保证整个拓扑图的所有路径之和最小,但不能保证任意两点之间是最短路径
  • 最短路径是从一点出发,到达目的地的路径最小。

所以本题的解题思路先用堆优化版迪杰斯特拉求各点到根节点的最短路径,然后用DFS从根节点找k条边的连通图(任意一个包含k条边的连通块就是答案)

因为 w <= 1e9,所以dist数组长度要用 long long 存

考查堆优化Dijkstra、DFS

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#define x first
#define y second

using namespace std;

typedef long long LL;
typedef pair<LL, int> PII;
const int N = 10e5 + 10, M = 2 * N;
int n, m, k;
int h[N], e[M], ne[M], idx, w[M], id[M];
LL dist[N];
bool st[N];

void add(int a, int b, int c, int d) {
    e[idx] = b;
    w[idx] = c;
    id[idx] = d;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dijkstra() {
    priority_queue<PII, vector<PII>, greater<PII>> heap;  // 定义为小根堆
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    heap.push({0, 1});
    while (heap.size()) {
        auto u = heap.top();
        heap.pop();
        if (st[u.y]) continue;
        st[u.y] = true;
        for (int i = h[u.y]; ~i; i = ne[i]) {
            int j = e[i];
            if (dist[j] > u.x + w[i]) {
                heap.push({u.x + w[i], j});
                dist[j] = u.x + w[i];
            }
        }
    }
}

vector<int> ans;
void dfs(int x) {
    st[x] = true;
    for (int i = h[x]; ~i; i = ne[i]) {
        int j = e[i];
        if (!st[j] && dist[x] + w[i] == dist[j]) {
            if (ans.size() < k) ans.push_back(id[i]);
            dfs(j);
        }
    }
}

int main() {
    cin >> n >> m >> k;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c, i);
        add(b, a, c, i);
    }
    dijkstra();
    memset(st, 0, sizeof st);
    dfs(1);
    cout << ans.size() << endl;
    for (auto i : ans) cout << i << " ";
    return 0;
}