【华为OD机试 】 服务失效判断(C++ Java JavaScript Python)

530 阅读1分钟

题目描述

某系统中有众多服务,每个服务用字符串(只包含字母和数字,长度<=10)唯一标识,服务间可能有依赖关系,如A依赖B,则当B故障时导致A也故障。

依赖具有传递性,如A依赖B,B依赖C,当C故障时导致B故障,也导致A故障。

给出所有依赖关系,以及当前已知故障服务,要求输出所有正常服务。

依赖关系:服务1-服务2 表示“服务1”依赖“服务2”

不必考虑输入异常,用例保证:依赖关系列表、故障列表非空,且依赖关系数,故障服务数都不会超过3000,服务标识格式正常。

输入描述

半角逗号分隔的依赖关系列表**(换行)**

半角逗号分隔的故障服务列表

输出描述

依赖关系列表中提及的所有服务中可以正常工作的服务列表,用半角逗号分隔,按依赖关系列表中出现的次序排序。

特别的,没有正常节点输出单独一个半角逗号

用例

输入a1-a2,a5-a6,a2-a3
a5,a2
输出a6,a3
说明

a1依赖a2,a2依赖a3,所以a2故障,导致a1不可用,但不影响a3;a5故障不影响a6。

所以可用的是a3、a6,在依赖关系列表中a6先出现,所以输出:a6,a3。

输入a1-a2
a2
输出,
说明a1依赖a2,a2故障导致a1也故障,没有正常节点,输出一个逗号。

参考

# 华为OD机试备考攻略 以及题库目录分值说明 考点说明

C++

#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <sstream>

using namespace std;

// 递归删除所有依赖于s的服务
void removeDependentServices(unordered_map<string, unordered_set<string>>& childServices, const string& service) {
    if (childServices.count(service)) {
        unordered_set<string> dependentServices = childServices[service];
        childServices.erase(service);

        for (const string& dependentService : dependentServices) {
            removeDependentServices(childServices, dependentService);
        }
    }
}

int main() {
    string relationsStr, breakdownsStr;
    getline(cin, relationsStr);
    getline(cin, breakdownsStr);

    // 解析依赖关系
    stringstream ss(relationsStr);
    string s;
    vector<vector<string>> relations;
    while (getline(ss, s, ',')) {
        stringstream ss2(s);
        string child, father;
        getline(ss2, child, '-');
        getline(ss2, father, '-');
        relations.push_back({child, father});
    }

    // 解析故障服务
    stringstream ss3(breakdownsStr);
    vector<string> breakdowns;
    while (getline(ss3, s, ',')) {
        breakdowns.push_back(s);
    }

    // 存储依赖关系
    unordered_map<string, unordered_set<string>> childServices; // 属性是父服务,属性值是子服务集合
    unordered_map<string, int> firstAppear; // 记录服务第一次出现的位置
    int i = 0;
    for (const auto& relation : relations) {
        const string& child = relation[0];
        const string& father = relation[1];

        childServices[child];
        childServices[father].insert(child);

        firstAppear[child] = i++;
        firstAppear[father] = i++;
    }

    // 删除所有故障服务及其依赖服务
    for (const string& breakdown : breakdowns) {
        removeDependentServices(childServices, breakdown);
    }

    // 输出正常服务
    vector<string> ans;
    ans.reserve(childServices.size());
    for (const auto& p : childServices) {
        ans.push_back(p.first);
    }

    // 如果没有正常服务,输出单独的半角逗号
    if (ans.empty()) {
        cout <<  "," << endl;
        return 0;
    }

    // 按照依赖关系列表中出现的次序排序
    sort(ans.begin(), ans.end(), [&](const string& a, const string& b) {
        return firstAppear[a] < firstAppear[b];
    });

    // 输出结果
    stringstream res;
    for (int i = 0; i < ans.size(); i++) {
        res << ans[i];
        if (i != ans.size() - 1) {
            res << ",";
        }
    }
    cout <<  res.str() << endl;

    return 0;
}