bluecode-找到内聚值最大的微服务群组

57 阅读2分钟

时间限制: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;
}