时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 256MB,其他语言 512MB
难度:中等
出题人:root
描述
开发团队为了调研微服务调用情况,对n个微服务调用数据进行了采集分析,微服务使用数字0至n-1进行编号,给你一个下标从0开始的数组edges ,其中 edges[i]表示存在一条从微服务i到微服务 edges[i]的接口调用。
我们将形成1个环的多个微服务称为微服务群组,一个微服务群组的所有微服务数量为L,能够访问到该微服务群组的微服务数量为V,这个微服务群组的内聚值H=L-V。
已知提供的数据中有1个或多个微服务群组,请按照内聚值H的结果从大到小的顺序对所有微服务群组(H相等时,取环中最大的数进行比较)排序,输出排在第一的微服务群组,输出时每个微服务群组输出的起始编号为环中最小的数。
输入描述
入参分为两行输入:
第一行为n,表示有n个微服务
第二行为数组 edges,其中 edges[i]表示存在一条从微服务i到微服务 edges[i]的接口调用,数字以空格分隔
输出描述
输出排在第-的微服务群组的编号数组,按照环的访问顺序输出,起始编号为环中最小的数,数字以空格分隔
用例输入 1 **
4
3 3 0 2
用例输出 1 **
0 3 2
用例输入 2 **
11
2 6 10 1 6 0 3 0 5 4 5 8
用例输出 2 **
0 2 10 5
提示
n==edges.length
2≤n≤10^5
0<=edges[i]<=n-1
edges[i]!=i
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <unordered_set>
#include <climits>
using namespace std;
vector<vector<int>> findCycles(int n, const vector<int>& edges) {
vector<bool> visited(n, false);
vector<vector<int>> cycles;
for (int i = 0; i < n; ++i) {
if (!visited[i]) {
vector<int> path;
int current = i;
while (true) {
if (visited[current]) {
auto it = find(path.begin(), path.end(), current);
if (it != path.end()) {
vector<int> cycle(it, path.end());
cycles.push_back(cycle);
}
break;
}
visited[current] = true;
path.push_back(current);
current = edges[current];
}
}
}
return cycles;
}
vector<vector<int>> buildReverseGraph(int n, const vector<int>& edges) {
vector<vector<int>> reverseGraph(n);
for (int u = 0; u < n; ++u) {
int v = edges[u];
reverseGraph[v].push_back(u);
}
return reverseGraph;
}
int calculateV(const vector<int>& cycle, const vector<vector<int>>& reverseGraph) {
unordered_set<int> cycleSet(cycle.begin(), cycle.end());
unordered_set<int> visitedBfs(cycle.begin(), cycle.end());
queue<int> q;
for (int node : cycle) {
q.push(node);
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : reverseGraph[u]) {
if (visitedBfs.find(v) == visitedBfs.end()) {
visitedBfs.insert(v);
q.push(v);
}
}
}
return visitedBfs.size() - cycle.size();
}
void reorderCycle(vector<int>& cycle) {
if (cycle.empty()) return;
int minNode = *min_element(cycle.begin(), cycle.end());
auto minIt = find(cycle.begin(), cycle.end(), minNode);
rotate(cycle.begin(), minIt, cycle.end());
}
int main() {
int n;
cin >> n;
vector<int> edges(n);
for (int i = 0; i < n; ++i) {
cin >> edges[i];
}
vector<vector<int>> cycles = findCycles(n, edges);
vector<vector<int>> reverseGraph = buildReverseGraph(n, edges);
vector<pair<pair<int, int>, vector<int>>> cycleInfo; // ((-H, -maxInCycle), cycle)
for (const auto& cycle : cycles) {
int L = cycle.size();
int V = calculateV(cycle, reverseGraph);
int H = L - V;
int maxInCycle = *max_element(cycle.begin(), cycle.end());
cycleInfo.emplace_back(make_pair(-H, -maxInCycle), cycle);
}
sort(cycleInfo.begin(), cycleInfo.end());
if (!cycleInfo.empty()) {
vector<int> selectedCycle = cycleInfo[0].second;
reorderCycle(selectedCycle);
for (size_t i = 0; i < selectedCycle.size(); ++i) {
if (i != 0) cout << " ";
cout << selectedCycle[i];
}
}
return 0;
}