算法训练营第七十天 | 最小生成树之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;
}
相关推荐
蹉跎x44 分钟前
力扣1358. 包含所有三种字符的子字符串数目
数据结构·算法·leetcode·职场和发展
巫师不要去魔法部乱说2 小时前
PyCharm专项训练4 最小生成树算法
算法·pycharm
IT猿手2 小时前
最新高性能多目标优化算法:多目标麋鹿优化算法(MOEHO)求解GLSMOP1-GLSMOP9及工程应用---盘式制动器设计,提供完整MATLAB代码
开发语言·算法·机器学习·matlab·强化学习
阿七想学习2 小时前
数据结构《排序》
java·数据结构·学习·算法·排序算法
王老师青少年编程2 小时前
gesp(二级)(12)洛谷:B3955:[GESP202403 二级] 小杨的日字矩阵
c++·算法·矩阵·gesp·csp·信奥赛
Kenneth風车3 小时前
【机器学习(九)】分类和回归任务-多层感知机(Multilayer Perceptron,MLP)算法-Sentosa_DSML社区版 (1)111
算法·机器学习·分类
eternal__day3 小时前
数据结构(哈希表(中)纯概念版)
java·数据结构·算法·哈希算法·推荐算法
APP 肖提莫3 小时前
MyBatis-Plus分页拦截器,源码的重构(重构total总数的计算逻辑)
java·前端·算法
OTWOL3 小时前
两道数组有关的OJ练习题
c语言·开发语言·数据结构·c++·算法
qq_433554544 小时前
C++ 面向对象编程:递增重载
开发语言·c++·算法