排队问题:C++实现高效解法
排队问题: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;
}
代码解析
- 数据结构:
inDegree:记录每个同学的入度,用于判断该同学是否可以作为队伍的队首。graph:使用哈希表存储图结构,graph[i]表示编号为i的同学后面的同学列表。teams:用来存储最终的队伍。q:队列用来进行拓扑排序,存放入度为 0 的同学。
- 拓扑排序:
- 初始化
inDegree和q。 - 循环遍历
q中的同学,将该同学加入当前队伍,并更新其后面同学的入度。 - 如果遇到
q为空,则再次循环遍历所有同学,查找入度为 0 的同学,并将它们加入q。 - 当
q不为空时,说明存在新的队伍,创建新的队伍并继续进行拓扑排序。
- 初始化
- 输出结果:
- 输出队伍数量
teams.size()。 - 循环遍历
teams,输出每个队伍的成员。
- 输出队伍数量
总结
该代码利用图数据结构和拓扑排序算法,能够在 O(n + m) 的时间复杂度内完成排队操作,并输出最终的队伍结构。代码清晰易懂,便于理解和扩展。
原文地址: https://www.cveoy.top/t/topic/qyGc 著作权归作者所有。请勿转载和采集!