排队问题:C++高效解法

题目描述

现在有 n 个小朋友(编号依次为 1, 2, ..., n)要排队。一开始他们各自为一队,接下来,老师会发布 m (≤ 1000)条命令,每条命令给出两个同学的编号 i, j,表示让 j 同学排到 i 同学后面。原先在 j 后面的同学则保持原来的队伍不变。 输出完成老师的 m 条指令以后,还剩下多少列队伍,并按照队首同学编号从小到大的顺序输出每个队伍,输出一个队伍时,按照从前到后的顺序输出队伍中每个同学的编号。

输入格式

从标准输入读入数据。 第一行,两个整数 n, m (1≤n,m≤1000)。 接下来 m 行,每行两个整数 i, j (1 ≤ i, j ≤ n,i ≠ j),表示让 j 同学排到 i 同学后面。

输出格式

输出到标准输出。 输出若干行。 第一行,一个整数 k ,表示执行完操作后的队伍数量。 接下来 k 行,按照队首同学编号从小到大的顺序输出每个队伍。每行输出一个队伍,输出一个队伍时,按照从前到后的顺序输出队伍中每个同学的编号。

样例 #1

样例输入 #1

5 5
3 5
4 2
5 4
5 4
2 4

样例输出 #1

3
1 
2 4 
3 5

代码实现

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

int main() {
    int n, m;
    cin >> n >> m;

    vector<int> inDegree(n + 1, 0); // 记录每个同学的入度
    unordered_map<int, vector<int>> graph; // 用哈希表存储图

    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        graph[a].push_back(b); // a同学的后面加上b同学
        inDegree[b]++; // b同学的入度加1
    }

    vector<vector<int>> teams; // 存储队伍
    queue<int> q; // 存储入度为0的同学

    for (int i = 1; i <= n; i++) {
        if (inDegree[i] == 0) {
            q.push(i);
        }
    }

    while (!q.empty()) {
        int cur = q.front();
        q.pop();

        for (int next : graph[cur]) {
            inDegree[next]--;

            if (inDegree[next] == 0) {
                q.push(next);
            }
        }

        teams.back().push_back(cur); // 将同学加入队伍

        if (q.empty()) {
            for (int i = 1; i <= n; i++) {
                if (inDegree[i] == 0) {
                    q.push(i);
                }
            }

            if (!q.empty()) {
                teams.push_back(vector<int>()); // 创建新的队伍
            }
        }
    }

    cout << teams.size() << endl;
    for (auto team : teams) {
        for (int member : team) {
            cout << member << " ";
        }
        cout << endl;
    }

    return 0;
}

代码解析

  1. 数据结构:
    • inDegree:记录每个同学的入度,用于判断该同学是否可以作为队伍的队首。
    • graph:使用哈希表存储图结构,graph[i] 表示编号为 i 的同学后面的同学列表。
    • teams:用来存储最终的队伍。
    • q:队列用来进行拓扑排序,存放入度为 0 的同学。
  2. 拓扑排序:
    • 初始化 inDegree 和 q。
    • 循环遍历 q 中的同学,将该同学加入当前队伍,并更新其后面同学的入度。
    • 如果遇到 q 为空,则再次循环遍历所有同学,查找入度为 0 的同学,并将它们加入 q。
    • 当 q 不为空时,说明存在新的队伍,创建新的队伍并继续进行拓扑排序。
  3. 输出结果:
    • 输出队伍数量 teams.size()。
    • 循环遍历 teams,输出每个队伍的成员。

总结

该代码利用图数据结构和拓扑排序算法,能够在 O(n + m) 的时间复杂度内完成排队操作,并输出最终的队伍结构。代码清晰易懂,便于理解和扩展。

排队问题:C++实现高效解法

原文地址: https://www.cveoy.top/t/topic/qyGc 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录