算法训练营第七十天 | 最小生成树之prim、最小生成树之Kruskal、拓扑排序

算法训练营第七十天

最小生成树之prim

题目链接:https://kamacoder.com/problempage.php?pid=1053

  • 随意将一个节点放入set作为初始状态。每次从和set中节点相连的权值最小的边相连的节点放入并记录权值。直到set大小和节点数相同。

代码如下:

cpp 复制代码
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std; 
int main() {
    int m, n, s, t;
    cin >> n >> m;
    vector<int> inDegree(n, 0); // 记录每个文件的入度
      
    unordered_map<int, vector<int>> umap;// 记录文件依赖关系 
    vector<int> result; // 记录结果
      
    while (m--) {
        // s->t,先有s才能有t
        cin >> s >> t;
        inDegree[t]++; // t的入度加一
        umap[s].push_back(t); // 记录s指向哪些文件
    } 
    queue<int> que;
    for (int i = 0; i < n; i++) {
        // 入度为0的文件,可以作为开头,先加入队列
        if (inDegree[i] == 0) que.push(i);  
        //cout << inDegree[i] << endl;
    }
    // int count = 0;
    while (que.size()) {
        int  cur = que.front(); // 当前选中的文件 
        que.pop();
        //count++;
        result.push_back(cur);
        vector<int> files = umap[cur]; //获取该文件指向的文件 
        if (files.size()) { // cur有后续文件
            for (int i = 0; i < files.size(); i++) {
                inDegree[files[i]] --; // cur的指向的文件入度-1
                if(inDegree[files[i]] == 0) que.push(files[i]);
            }
        }
    }
    if (result.size() == n) {
        for (int i = 0; i < n - 1; i++) cout << result[i] << " ";
        cout << result[n - 1];
    } else cout << -1 << endl;
      
      
}

最小生成树之Kruskal

题目链接:https://kamacoder.com/problempage.php?pid=1191[](https://kamacoder.com/problempage.php?pid=1191)

  • 用到了并查集,每次对两个节点不连通的情况进行处理,记录最小权值的边。之后对两个节点使用并查集中的join,直到没有不连通的节点

代码如下:

cpp 复制代码
#include <iostream>
#include <vector>

using namespace std;

int father[10001];

void init() {
    for (int i = 0; i <= 10000; i++) father[i] = i;
}

int find(int a) {
    while (father[a] != a) {
        a = father[a];
    }
    return a;
}

bool isSame(int a, int b) {
    a = find(a);
    b = find(b);
    return a == b;
}

void join(int a, int b) {
    if (isSame(a, b)) return;
    father[find(a)] = b;
    return;
}

int main() {
    int v, e;
    cin >> v >> e;
    vector<vector<int>> edges(e, vector<int>(3, 0));
    for (int i = 0; i < e; i++) {
        for (int j = 0; j < 3; j++) {
            cin >> edges[i][j];
        }
    }
    int dis = 0;
    init();
    bool flag = true;
    while (flag) {
        flag = false;
        int min = 10000;
        int minIndex = -1;
        for (int i = 0; i < e; i++) {
            if (isSame(edges[i][0], edges[i][1])) continue;
            flag = true;
            if (min > edges[i][2]) {
                min = edges[i][2];
                minIndex = i;
            }
        }
        if (flag == true) {
            dis += min;
            join(edges[minIndex][0], edges[minIndex][1]);
        }
    }
    cout << dis << endl;
}

软件构建

  • 这题之前一次笔试写过,当时最后一个元素后也加了空格,导致只过了30%,大家注意下
    代码如下:
cpp 复制代码
#include <iostream>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
 
int main() {
    int n, m;
    cin >> n >> m;
    queue<long int> my_resque;
    queue<long int> my_midque;
    map<long int, set<long int>> mymap;
    map<long int, long int> nummap;
    set<long int> res;
    int flag = 0;
    for (int i = 0; i < n; i++) nummap[i] = 0;
    for (int i = 0; i < m; i++) {
        long int a, b;
        cin >> a >> b;
        mymap[b].insert(a);
        nummap[b]=mymap[b].size();
    }
    while (res.size() < n) {
        int num = res.size();
        for (int i = 0; i < n; i++) {
            if (res.find(i) == res.end() && nummap[i] == 0) {
                my_midque.push(i);
                res.insert(i);
                my_resque.push(i);
            }
        }
        if (num == res.size() && num != n) break;
        while (!my_midque.empty()) {
            long int t = my_midque.front();
            my_midque.pop();
            for (int i = 0; i < n; i++) {
                if (res.find(i) == res.end() &&
                    nummap[i] > 0 && mymap[i].find(t) != mymap[i].end())
                    nummap[i]--;
            }
        }
    }
    if (res.size() < n) cout << -1 << endl;
    else {
        while (!my_resque.empty()) 
        {
            if (my_resque.size() > 1)
                cout << my_resque.front() << ' ';
            else cout << my_resque.front();
            my_resque.pop();
        }
        cout << endl;
    }
    return 0;
}
相关推荐
CHHH_HHH36 分钟前
【C++11】深入解析C++可变参数模板
开发语言·c++·算法·stl·c++11
hurrycry_小亦36 分钟前
洛谷题目:P1215 [USACO1.4] 母亲的牛奶 Mother‘s Milk 题解(本题简)
算法
KJ_BioMed2 小时前
从PDB到高亲和力分子:De novo生成式计算化学Pipeline剖析
算法·生物医药·生物科研·科研干货·化合物设计
一个王同学2 小时前
从零到一 | CV转多模态大模型 | week17 | LLM 推理优化 & vLLM 详解
人工智能·深度学习·算法·机器学习·计算机视觉·vllm
旖-旎4 小时前
《LeetCode 53 最大子数组和 || LeetCode 918 环形子数组的最大和》
c++·算法·leetcode·动态规划
变量未定义~4 小时前
单调栈+倍增思想 皇家守卫【算法赛】、单调队列 附近最小
算法
QN1幻化引擎4 小时前
给 AI 做一次「意识体检」——基于 QN1 幻化引擎的灵鉴意识识别框架与 DalinX V5 实测
大数据·数据结构·人工智能·算法·架构
拂拉氏4 小时前
【知识讲解】 AVL树从基本成员的介绍到核心接口的实现(插入、判断、删除等等)
数据结构·算法·avl树
可靠的仙人掌5 小时前
SAC(Soft Actor-Critic)算法底座
开发语言·算法·php
c238565 小时前
《动态规划:从“傻傻穷举”到“过目不忘”的修仙之路》
c++·算法·动态规划