7/29 拓扑排序

本文介绍拓扑排序的概念,即如何将有向无环图的所有顶点排列成线性序列,满足边的顺序。通过寻找入度为0的节点,不断删除边并更新入度,直至遍历所有节点。给出了一个拓扑排序的实例,用于解决HDOJ的确定比赛名次问题,展示了一种实际应用拓扑排序的方法。

所谓”拓扑排序“,就是指将一个有向无环图G的所有顶点排成一个线性序列,使得有向无环图G的 边集中的任意一条边<u,v>,始终满足u出现在v的前面。

所以实现拓扑排序其实非常简单,只需要找到入度为0的节点。然后删除与之相连的边,更新入度即可,直到所有点都被遍历过即可。

来道板子题

hdu 1285 

// Problem: 确定比赛名次
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=1285
// Memory Limit: 65 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;
const int N = 505;
int g[N][N];
int in[N], out[N];
void topsort(int n)
{
    int k = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (!in[j])
            {
                k = j;
                out[i] = j;
                in[j]--;
                break;
            }
        }
        for (int j = 1; j <= n; j++)
        {
            if (g[k][j] == 1)
            {
                g[k][j] = 0;
                in[j]--;
            }
        }
    }
}
int main()
{
    int n, m;
    while (cin >> n >> m)
    {
        memset(g, 0, sizeof(g));
        memset(in, 0, sizeof(in));
        while (m--)
        {
            int x, y;
            cin >> x >> y;
            if (g[x][y])
                continue;
            g[x][y] = 1;
            in[y]++;
        }
        topsort(n);
        for (int i = 1; i <= n; i++)
        {
            if (i == n)
                printf("%d\n", out[i]);
            else
                printf("%d ", out[i]);
        }
    }
}

### 哈夫曼编码算法实现 以下代码实现了从叶子到根逆向求每个字符的哈夫曼编码,基于用户提供的伪代码逻辑[^1]。 #### 代码实现 ```cpp #include <iostream> #include <vector> #include <queue> #include <string> using namespace std; // 定义哈夫曼树节点结构 struct HFMNode { int weight; // 权重 char data; // 数据(字符) HFMNode* left; HFMNode* right; HFMNode(int w, char d) : weight(w), data(d), left(nullptr), right(nullptr) {} }; // 比较函数用于优先队列 struct Compare { bool operator()(HFMNode* a, HFMNode* b) { return a->weight > b->weight; } }; // 构建哈夫曼树 HFMNode* buildHuffmanTree(const vector<pair<char, int>>& freq) { priority_queue<HFMNode*, vector<HFMNode*>, Compare> pq; // 将每个字符及其频率作为叶子节点优先队列 for (const auto& p : freq) { pq.push(new HFMNode(p.second, p.first)); } // 自底向上构建哈夫曼树 while (pq.size() > 1) { HFMNode* left = pq.top(); pq.pop(); HFMNode* right = pq.top(); pq.pop(); HFMNode* parent = new HFMNode(left->weight + right->weight, '\0'); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); // 返回根节点 } // 生成编码并存储在映射中 void generateCodes(HFMNode* root, string code, unordered_map<char, string>& codes) { if (!root) return; // 如果是叶子节点,则记录编码 if (!root->left && !root->right) { codes[root->data] = code; return; } generateCodes(root->left, code + "0", codes); generateCodes(root->right, code + "1", codes); } // 主函数 int main() { int n; cin >> n; vector<pair<char, int>> freq(n); // 输字符及其频率 for (int i = 0; i < n; ++i) { cin >> freq[i].second; // 频率 freq[i].first = 'a' + i; // 假设字符为'a', 'b', 'c'... } // 构建哈夫曼树 HFMNode* root = buildHuffmanTree(freq); // 生成编码 unordered_map<char, string> codes; generateCodes(root, "", codes); // 输出编码结果 for (int i = 0; i < n; ++i) { cout << codes[freq[i].first]; if (i != n - 1) { cout << " "; } } cout << endl; return 0; } ``` #### 输输出示例 **输:** ``` 8 5 29 7 8 14 23 3 11 ``` **输出:** ``` 0110 10 1110 1111 110 00 0111 010 ``` --- ### 拓扑排序算法实现 以下代码实现了有向无环(DAG)的拓扑排序算法,基于邻接表存储结构[^2]。 #### 代码实现 ```cpp #include <iostream> #include <vector> #include <queue> using namespace std; // 拓扑排序 vector<int> topologicalSort(const vector<vector<int>>& graph, int n) { vector<int> inDegree(n, 0); // 数组 queue<int> q; vector<int> result; // 计算所有节点 for (int u = 0; u < n; ++u) { for (int v : graph[u]) { inDegree[v]++; } } // 将为0的节点队 for (int i = 0; i < n; ++i) { if (inDegree[i] == 0) { q.push(i); } } // 拓扑排序过程 while (!q.empty()) { int u = q.front(); q.pop(); result.push_back(u); for (int v : graph[u]) { if (--inDegree[v] == 0) { q.push(v); } } } return result; } // 主函数 int main() { int n, m; cin >> n >> m; // n: 节点数, m: 边数 vector<vector<int>> graph(n); for (int i = 0; i < m; ++i) { int u, v; cin >> u >> v; // 输边 u -> v graph[u].push_back(v); } // 拓扑排序 vector<int> sortedOrder = topologicalSort(graph, n); // 输出排序结果 for (size_t i = 0; i < sortedOrder.size(); ++i) { cout << sortedOrder[i]; if (i != sortedOrder.size() - 1) { cout << " "; } } cout << endl; return 0; } ``` #### 输输出示例 **输:** ``` 6 6 5 2 5 0 4 0 4 1 2 3 3 1 ``` **输出:** ``` 4 5 0 2 3 1 ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值