C++ 算法竞赛、02 周赛篇 | AcWing 第2场周赛

AcWing 第2场周赛

竞赛 - AcWing

3626 三元一次方程

AcWing 3626. 三元一次方程 - AcWing

image-20230906152907705

两层循环

#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⭐最大差值

3627. 最大差值 - AcWing题库

image-20230906160257775

考查贪心,所有输入的不是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⭐⭐边的删减

3628. 边的删减 - AcWing题库

image-20230906164624612

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

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

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

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

考查堆优化Dijkstra、DFS,理论请看

C++算法之旅、06 基础篇 | 第三章 图论 - 小能日记 - 博客园 (cnblogs.com)

#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;
}

img

posted @ 2023-09-06 18:50  小能日记  阅读(48)  评论(0编辑  收藏  举报