迪杰斯特拉算法
华为20240417机考
//云上故障逃生
//在云上多个业务节点之间选择最快的逃生节点集,并考虑每个节点的剩余业务容量。
//有一个网络时延表,表示每个节点到其他节点的通信延迟;还有一个剩余业务容量表,
//表示每个节点的剩余业务容量。在一个节点故障时,需要选择一个或多个逃生节点,
//确保逃生路径的时延最小,并且逃生节点集各节点剩余容量的总和足够容纳故障节点的业务量,
//当故障节点与多个节点最短距离相同,优先选择编号较小的节点容灾,
//如果逃生节点集中多个节点最短距离相同时按编号从小到大的顺序排列。
//
//解答要求
//时间限制 : C / C++ 1000ms, 其他语言:2000ms
//
//内存限制 : C / C++ 256MB, 其他语言:512MB
//输入
//第1行n表示云上业务节点数, 2 <= n <= 10000,节点编号从0开始,依次递增;
//第2到1 + n行表示业务节点间的网络时延矩阵表delayMatrix,delayMatrix[i][j] 表示节点 i 到节点 j 的通信时延;
//1)如果节点 i 和节点 j 之间没有直接相连的边,则 delayMatrix[i][j] 为 -1,第i个节点和它自己也没有边,
// 所以delayMatrix[i][i] = -1
//2)节点间有边时延范围为 1 <= delayMatrix[i][j] <= 1000,矩阵元素间使用空格分割
//另,输入保证 delayMatrix[i][j] == delayMatrix[j][i]
//第2 + n行表示各业务节点的剩余容量表 remainingCapacity,其中 remainingCapacity[i] 表示节点 i 的剩余业务容量,
// 业务量的范围1 <= remainingCapacity[i] <= 100,数组元素间使用空格分割;
//第3 + n行表示故障业务节点编号 faultyNode,表示发生故障的节点,取值范围为 0 <= faultyNode <= n−1 ;
//第4 + n行表示受损业务节点需要迁移的业务量, 受损业务量的范围(0−1000] 。
//输出
//返回符合条件的逃生路径节点编号列表(以单空格间隔),当所有节点都不够故障节点业务容灾的时候输出所有容灾节点。
// 参数说明:
// * vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。
// * prev -- 前驱顶点数组。
// 即prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中位于"顶点i"之前的那个顶点。
// * dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <map>
#include <algorithm>
using namespace std;
#define INF (0x7FFFFFFF)
// 初始化图(由点及边组成)
class Solution{
public:
vector<int> dijkstra(int n, vector<vector<int>>& delayMatrix, vector<int>& remainingCapacity,
int faultyNode, int migration_task){
vector<int> prev(n, 0); // 记录最短路径的顶点
vector<int> dist(n, 0); // 定点i的最短路径为错误节点faultyNode到点i的延时
vector<int> flag(n, 0); // flag[i] = 1表示错误节点i的最短路径已经获取
vector<int> result;
// 初始化
for(int i = 0; i < n; i++){
if(delayMatrix[faultyNode][i] == -1){
dist[i] = INF;
}else{
dist[i] = delayMatrix[faultyNode][i];
}
}
flag[faultyNode] = 1;
dist[faultyNode] = 0;
int min, k;
// 已找到最短路径节点列表计为S,未获得的节点列表计为U
for(int i = 1; i < n; i++){
// 在未获得的节点列表U中找距离faultyNode最短的节点
min = INF;
for(int j = 0; j < n; j++){
if(!flag[j] && dist[j] < min){
min = dist[j];
k = j;
}
}
flag[k] = 1;
int temp;
// 更新dist
for(int j = 0; j < n; j++){
temp = (delayMatrix[k][j] == -1 ? INF : delayMatrix[k][j]);
if(!flag[j] && (temp < dist[j])){
dist[j] = temp;
prev[j] = k;
}
}
}
map<int, int> dist_node;
for(int i = 0; i < n; i++){
dist_node[dist[i]] = i;
}
// sort(dist_node.begin(), dist_node.end());
int cnt = 0;
for(const auto& it : dist_node){
if(it.second != faultyNode){
cnt += remainingCapacity[it.second];
result.push_back(it.second);
if(cnt >= migration_task){
break;
}
}
}
return result;
}
};
int main(){
int n;
cin >> n; cin.ignore();
int temp = n;
vector<vector<int>> delayMatrix;
while(temp--){
string line;
getline(cin, line);
string k;
istringstream iss(line);
vector<int> line_vec;
while(iss >> k){
line_vec.push_back(stoi(k));
}
delayMatrix.push_back(line_vec);
}
vector<int> remainingCapacity;
temp = n;
string line_1;
getline(cin, line_1);
istringstream iss_1(line_1);
string k_1;
while(iss_1 >> k_1){
remainingCapacity.push_back(stoi(k_1));
}
int faultyNode;
cin >> faultyNode;
int migration_task;
cin >> migration_task;
Solution sol;
vector<int> result = sol.dijkstra(n, delayMatrix, remainingCapacity, faultyNode, migration_task);
for(int i = 0; i < result.size()-1; i++){
cout << result[i] << " ";
}
cout << result[result.size()-1];
return 0;
}