题目要求对每个节点 (从 1 到
),将其所有出边指向的节点
按照权值
从小到大排序,权值相同时按节点编号从小到大排序。然后依次输出每个节点
的出边指向的节点序列(按
从小到大输出)。
解题思路
- 存储结构:使用邻接表(
vector<vector<int>> edges)存储每个节点的出边。edges[u]存储所有从出发指向的节点
。
- 排序规则:对于每个节点
,对其邻接表
edges[u]排序:- 首先比较节点
的权值
,权值小的在前。
- 若权值相同,则比较节点编号
,编号小的在前。
- 首先比较节点
- 输出格式:
- 每行对应一个节点
(从 1 到
)。
- 若节点
没有出边,输出空行。
- 否则,按排序后的顺序输出节点编号,空格分隔,行末无多余空格。
- 每行对应一个节点
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
vector<int> w(n + 1);
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
vector<vector<int>> edges(n + 1);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
edges[u].push_back(v);
}
// 对每个节点的出边列表排序
for (int u = 1; u <= n; u++) {
sort(edges[u].begin(), edges[u].end(), [&](int a, int b) {
if (w[a] != w[b]) {
return w[a] < w[b];
}
return a < b;
});
}
// 输出结果
for (int u = 1; u <= n; u++) {
if (edges[u].empty()) {
cout << "\n";
continue;
}
for (int i = 0; i < edges[u].size(); i++) {
if (i > 0) cout << " ";
cout << edges[u][i];
}
cout << "\n";
}
}
return 0;
}
算法复杂度分析
-
时间复杂度:
- 构建邻接表:
- 排序操作:设节点
的出度为
,排序单个邻接表耗时
- 总排序时间:
- 最坏情况(完全图):
,总时间
- 一般情况(稀疏图):
(平均出度),总时间
- 最坏情况(完全图):
- 总时间复杂度:
(
通常主导)
组数据总时间:
- 构建邻接表:
-
空间复杂度:
- 存储权值数组:
- 邻接表:
- 总空间复杂度:
- 存储权值数组:

京公网安备 11010502036488号