算法训练营第七十天 | 最小生成树之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;
}
相关推荐
想跑步的小弱鸡4 小时前
Leetcode hot 100(day 3)
算法·leetcode·职场和发展
xyliiiiiL5 小时前
ZGC初步了解
java·jvm·算法
爱的叹息6 小时前
RedisTemplate 的 6 个可配置序列化器属性对比
算法·哈希算法
独好紫罗兰6 小时前
洛谷题单2-P5713 【深基3.例5】洛谷团队系统-python-流程图重构
开发语言·python·算法
每次的天空7 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法
请来次降维打击!!!7 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
qystca7 小时前
蓝桥云客 刷题统计
算法·模拟
别NULL8 小时前
机试题——统计最少媒体包发送源个数
c++·算法·媒体
weisian1518 小时前
Java常用工具算法-3--加密算法2--非对称加密算法(RSA常用,ECC,DSA)
java·开发语言·算法
程序员黄同学9 小时前
贪心算法,其优缺点是什么?
算法·贪心算法