- 117. 软件构建
拓扑排序,每次选择入度为0的节点,然后去掉这个节点,将它所指向的所有节点的入度都减一,然后将入度为0的新节点入队,重复上述操作直到队列为空;如果结果没有包含所有节点,那么就代表有环
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
int main() {
int n = 0, m = 0;
cin >> n >> m;
vector<vector<int>> edges(n);
vector<int> indegree(n, 0);
int from, to;
for (int i = 0; i < m; ++i) {
cin >> from >> to;
edges[from].push_back(to);
indegree[to]++;
}
queue<int> q;
for (int i = 0; i < n; ++i) {
if (indegree[i] == 0) {
q.push(i);
}
}
vector<int> result;
while (!q.empty()) {
int file = q.front();
result.push_back(file);
q.pop();
for (int next : edges[file]) {
indegree[next]--;
if (indegree[next] == 0) {
q.push(next);
}
}
}
if (result.size() == n) {
for (int i = 0; i < n - 1; i++)
cout << result[i] << " ";
cout << result[n - 1];
} else {
cout << -1 << endl;
}
return 0;
}
- 47. 参加科学大会(第六期模拟笔试)
Dijkstra算法,适用于有向图、边的权值没有负数,解决一个点到其他所有点的最短路径;采用贪心策略。维护一个集合S,包含已找到最短路径的节点。每次从集合S之外的节点中,选择一个距离源点最近的节点加入S,并松弛(更新)其所有邻居的距离。
- 准备distance数组,保存源点到i点的最短距离;准备visited数组,记录节点i是否从小根堆中弹出过
- 准备小根堆,保存节点i以及源点到节点i的距离(邻接表保存i和源点到i的距离,邻接矩阵保存x,y与源点到i的距离),小根堆根据距离组织
- 默认情况:
std::less → 大根堆 → 较大的元素在堆顶
- 比较函数返回true表示第一个参数应该排在第二个参数后面
- 设置distance[源点]为0,将(源点k, 0)加入小根堆
- 从小根堆中弹出节点(u, dis),然后:
- 如果visited[u]为true,continue。
- 如果visited[u]为false,设置visited[u]为true,然后检查u的所有边(k, weight):
- 检查是否越界(需要的话)
- 检查visited[k]== false且distance[u] + weight < distance[k],则更新distance[k]=distance[u] + weight,并将(k, distance[k])加入小根堆
- 处理u的所有边后,重复步骤4
- 小根堆为空,流程结束,distance表记录了源点到其他点的最短距离
#include <climits>
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
int main() {
int n = 0, m = 0;
cin >> n >> m;
vector<vector<int>> edges(n + 1, vector<int>(n + 1, INT_MAX));
int from, to, weight;
for (int j = 0; j < m; j++) {
cin >> from >> to >> weight;
edges[from][to] = weight;
}
int start = 1;
int end = n;
vector<int> distance(n + 1, INT_MAX);
vector<bool> visited(n + 1);
distance[start] = 0;
for (int i = 1; i <= n; ++i) {
int curr = 1;
int minVal = INT_MAX;
for (int j = 1; j <= n; ++j) {
if (!visited[j] && minVal > distance[j]) {
curr = j;
minVal = distance[j];
}
}
visited[curr] = true;
for (int j = 1; j <= n; ++j) {
if (!visited[j] && edges[curr][j] != INT_MAX &&
distance[j] > distance[curr] + edges[curr][j]) {
distance[j] = distance[curr] + edges[curr][j];
}
}
}
if (distance[end] == INT_MAX) {
cout << -1 << endl;
} else {
cout << distance[end] << endl;
}
return 0;
}
{
struct CompareSecond
{
bool operator()(pair<int, int>left, pair<int, int>right)
{
return left.second > right.second;
}
};
class Solution {
public:
int dir[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };
int networkDelayTime(vector<vector<int>>& times, int n, int k) {
vector<vector<int>> network(n, vector<int>(n, INT_MAX));
for (int i = 0; i < times.size(); ++i) {
network[times[i][0] - 1][times[i][1] - 1] = times[i][2];
}
vector<int> distance(n, INT_MAX);
vector<int> visited(n, false);
priority_queue
<
pair<int, int>,
vector<pair<int, int>>,
CompareSecond
> pq;
distance[k-1] = 0;
pq.push(make_pair(k-1, 0));
while (!pq.empty())
{
auto info = pq.top();
pq.pop();
int u = info.first;
int dis = info.second;
if (visited[u]) continue;
visited[u] = true;
for (int i = 0; i < n; ++i) {
if (network[u][i] != INT_MAX) {
if (!visited[i] &&
distance[u] + network[u][i] < distance[i]) {
distance[i] = distance[u] + network[u][i];
pq.push(make_pair(i, distance[i]));
}
}
}
}
int ans = -1;
for (int i = 0; i < n; ++i) {
if (distance[i] == INT_MAX) return -1;
ans = max(ans, distance[i]);
}
return ans;
}
};
}