题目描述
某系统中有众多服务,每个服务用字符串(只包含字母和数字,长度<=10)唯一标识,服务间可能有依赖关系,如A依赖B,则当B故障时导致A也故障。
依赖具有传递性,如A依赖B,B依赖C,当C故障时导致B故障,也导致A故障。
给出所有依赖关系,以及当前已知故障服务,要求输出所有正常服务。
依赖关系:服务1-服务2 表示“服务1”依赖“服务2”
不必考虑输入异常,用例保证:依赖关系列表、故障列表非空,且依赖关系数,故障服务数都不会超过3000,服务标识格式正常。
输入描述
半角逗号分隔的依赖关系列表**(换行)**
半角逗号分隔的故障服务列表
输出描述
依赖关系列表中提及的所有服务中可以正常工作的服务列表,用半角逗号分隔,按依赖关系列表中出现的次序排序。
特别的,没有正常节点输出单独一个半角逗号。
用例
| 输入 | a1-a2,a5-a6,a2-a3a5,a2 |
| 输出 | a6,a3 |
| 说明 | a1依赖a2,a2依赖a3,所以a2故障,导致a1不可用,但不影响a3;a5故障不影响a6。 所以可用的是a3、a6,在依赖关系列表中a6先出现,所以输出:a6,a3。 |
| 输入 | a1-a2a2 |
| 输出 | , |
| 说明 | 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;
}