117. 软件构建
拓扑排序代码实现。每次将入度为0的结点加入结果列表,同时该结点的所有子节点(有向边指向的结点)入度减一。
拓扑排序使用与有向无环图(DAG),若有环则无法进行排序。
时间复杂度:
O
(
n
3
)
O(n^3)
O(n3)
空间复杂度:
O
(
n
)
O(n)
O(n)
暴力版
// c++
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, m;
cin>>n>>m;
vector<vector<int>> edges(n+1, vector<int>(n+1, 0));
vector<int> inDegree(n+1, 0);
vector<int> result;
int left, right;
for(int i=0; i<m; i++){
cin>>left>>right;
edges[left][right] = 1;
inDegree[right]++;
}
for(int i=0; i<n; i++){
bool isChange = false;
for(int j=0; j<n; j++){
if(!inDegree[j]){
result.emplace_back(j);
// 更新结点入度
for(int k=0; k<n; k++){
if(edges[j][k]){
inDegree[k]--;
}
}
inDegree[j] = -1;
isChange = true;
}
}
// 没有入度为0的结点:1.全部都排序完毕 2.有环
if(!isChange) {
break;
}
}
if(result.size()!=n) cout<<-1;
else{
for(int i=0; i<result.size(); i++){
if(i==0) cout<<result[i];
else cout<<" "<<result[i];
}
}
return 0;
}
广搜版
时间复杂度:
O
(
V
+
E
)
O(V + E)
O(V+E)
空间复杂度:
O
(
n
)
O(n)
O(n)
//c++
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, m;
cin>>n>>m;
// vector<vector<int>> edges(n+1, vector<int>(n+1, 0));
// 记录入度
vector<int> inDegree(n+1, 0);
// 记录结果
vector<int> result;
// 存储依赖关系
unordered_map<int, vector<int>> umap;
// 用于存储广搜节点
queue<int> que;
int left, right;
for(int i=0; i<m; i++){
cin>>left>>right;
// edges[left][right] = 1;
inDegree[right]++;
umap[left].emplace_back(right);
}
for(int i=0; i<n; i++) {
if(!inDegree[i]) que.push(i);
}
while(!que.empty()){
int cur = que.front();
// 将当前节点加入结果列表
result.emplace_back(cur);
que.pop();
vector<int> children = umap[cur];
// 更新当前节点的子节点的入度
for(int i=0; i<children.size(); i++){
inDegree[children[i]]--;
// 出现入度为0的结点存入队列
if(!inDegree[children[i]]) que.push(children[i]);
}
}
if(result.size()!=n) cout<<-1;
else{
for(int i=0; i<result.size(); i++){
if(i==0) cout<<result[i];
else cout<<" "<<result[i];
}
}
return 0;
}
总结
使用BFS实现拓扑排序,若用邻接矩阵存储图,时间复杂度为O(V2);若用邻接表存储图,时间复杂度为O(V + E)。
47. 参加科学大会(第六期模拟笔试)
Dijkstra 算法代码实现,与Prim算法类似。
Dijkstra 算法讲解
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
// c++
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, m;
cin>>n>>m;
vector<vector<int>> edges(n+1, vector<int>(n+1, INT_MAX));
vector<bool> visited(n+1, false);
vector<int> minDist(n+1, INT_MAX);
int result = 0;
int left, right, val;
for(int i=0; i<m; i++){
cin>>left>>right>>val;
edges[left][right] = val;
}
for(int i=2; i<=n; i++) {
minDist[i] = edges[1][i];
}
minDist[1] = 0;
for(int i=1; i<=n; i++){
int cur = 1;
int minVal = INT_MAX;
// 找最近的结点
for(int j=1; j<=n; j++){
if(minDist[j]<minVal && !visited[j]){
minVal = minDist[j];
cur = j;
}
// cout<<minDist[j]<<" ";
}
// cout<<endl;
visited[cur] = true;
// cout<<cur<<" "<<result<<endl;
for(int j=2; j<=n; j++){
if(!visited[j] && edges[cur][j]!=INT_MAX){
minDist[j] = min(minDist[j], minVal+edges[cur][j]);
}
}
}
if(minDist[n]!=INT_MAX) cout<<minDist[n];
else cout<<-1;
return 0;
}