2018年7月17日,阿里在線編程測驗,題幹如下,它最後面的兩條註釋應該有說反了依賴關係。
今天我們看到的阿里巴巴提供的任何一項服務後邊都有着無數子系統和組件的支撐,子系統之間也互相依賴關聯,
其中任意一個環節出現問題都可能對上游鏈路產生影響。小明做爲新人接收到的第一個任務就是去梳理所有的依賴關係,
小明和每個系統的負責人確認了依賴關係,記錄下調用對應系統的耗時,用這些數據分析端到端鏈路的數目和鏈路上最長的耗時。
輸入: 小明蒐集到的系統耗時和依賴列表
5 4 // 表示有5個系統和 4個依賴關係
3 // 調用1號系統耗時 3 ms
2 // 調用2號系統耗時 2 ms
10 // 調用3號系統耗時 10 ms
5 // 調用4號系統耗時 5 ms
7 // 調用5號系統耗時 7 ms
1 2 // 2號系統依賴1號系統
1 3 // 3號系統依賴1號系統
2 5 // 2號系統依賴5號系統
4 5 // 4號系統依賴5號系統
輸出: 調用鏈路的數目 和最大的耗時, 這裏有三條鏈路1->2->5,1->3, 4->5,最大的耗時是1到3的鏈路 3+10 = 13,無需考慮環形依賴的存在。
3 13
利用回溯法即可
首先用一個vector保存每個系統的耗時,然後用一個multimap保存依賴關係樹,同時保存一個是否是頭節點的布爾數組。
#include <map>
#include <iostream>
#include <vector>
using namespace std;
void findPath(multimap<int, int> &m_sRelev, vector<double> &timeUsed,
vector<int>& path, vector<vector<int> > &paths, int key, int &time, int &maxTime) {
multimap<int, int>::iterator iter;
time += timeUsed[key];
path.push_back(key);
if ((iter = m_sRelev.find(key)) != m_sRelev.end()) {//有孩子
int n = m_sRelev.count(key);
for (int j = 0; j < n; ++j, ++iter) {
findPath(m_sRelev, timeUsed, path, paths, iter->second, time, maxTime);
}
} else {//子節點
paths.push_back(path);
if (maxTime < time)
maxTime = time;
}
time -= timeUsed[key];
path.pop_back();
}
int main()
{
int numSystem, numRelev;
while (cin >> numSystem >> numRelev) {
vector<double> timeUsed(numSystem+1);//保存時間
bool* isHead = new bool[numSystem + 1];//該系統是否要依賴其它系統
memset(isHead, 1, numSystem + 1);//首先全部置爲true
multimap<int, int> m_sRelev;//依賴關係
int maxTime = 0;
vector<vector<int> > paths;
for (int i = 1; i <= numSystem; ++i) {
double time;
cin >> time;
timeUsed[i] = time;
}
for (int i = 0; i < numRelev; ++i) {
int sysMaster, sysSlave;
cin >> sysMaster >> sysSlave;
m_sRelev.insert(make_pair(sysMaster, sysSlave));
isHead[sysSlave] = false;//依賴其它系統,那麼不能作爲鏈路的開端
}
for (int i = 1; i <= numSystem; ++i) {
if (isHead[i]) {//如果是鏈路的開端
int time = 0;
vector<int>path;
findPath(m_sRelev, timeUsed, path, paths, i, time, maxTime);
}
}
delete[] isHead;
cout << paths.size() << " " << maxTime << endl;
}
return 0;
}