[2023年3月12日]十四届蓝桥杯C++选拔赛中高级(第二子卷、编程题(4、收集宝石))

参考程序(回溯+剪枝)

#include <iostream>
#include <vector>
using namespace std;

int N, M;
vector<vector<int>> graph; // 邻接表
vector<bool> visited;
int maxCount = 0;

void backtrack(int node, int count) {
    if (node == N) { // 遍历到所有节点
        maxCount = max(maxCount, count);
        return;
    }

    // 检查是否可以选择当前节点
    bool canPick = true;
    for (int i = 0; i < node; i++) {
        if (visited[i] && graph[node][i]) { // 冲突
            canPick = false;
            break;
        }
    }

    // 选择当前节点
    if (canPick) {
        visited[node] = true;
        backtrack(node + 1, count + 1);
        visited[node] = false;
    }

    // 不选择当前节点
    backtrack(node + 1, count);
}

int main() {
    cin >> N >> M;
    graph.resize(N, vector<int>(N, 0));
    visited.resize(N, false);

    // 输入相冲信息,构建邻接表
    for (int i = 0; i < M; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        graph[u][v] = graph[v][u] = 1; // 无向边
    }

    backtrack(0, 0); // 从第0个节点开始回溯
    cout << maxCount << endl;

    return 0;
}

参考程序(贪心算)

#include <iostream>
#include <vector>
#include <set>
using namespace std;

int main() {
    int N, M;
    cin >> N >> M;

    vector<set<int>> graph(N); // 邻接表表示图
    for (int i = 0; i < M; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        graph[u].insert(v);
        graph[v].insert(u);
    }

    vector<bool> visited(N, false);
    int maxCount = 0;

    while (true) {
        // 找到度数最小的节点
        int minDegree = N + 1, selected = -1;
        for (int i = 0; i < N; i++) {
            if (!visited[i] && graph[i].size() < minDegree) {
                minDegree = graph[i].size();
                selected = i;
            }
        }

        if (selected == -1) break; // 没有可以选择的节点了

        // 选择该节点加入独立集
        maxCount++;
        visited[selected] = true;

        // 移除与该节点相邻的节点
        for (int neighbor : graph[selected]) {
            visited[neighbor] = true;
        }
    }

    cout << maxCount << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汉克老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值