Algorithm (알고리즘)
Algorithm - Topological Sort (위상정렬)
강태종
2020. 9. 8. 12:26
개념
어떤 일을 할 때 순서를 찾는 알고리즘이다
.
작동원리
1. InDegree가 0인 정점을 queue에 넣는다.
2. queue에서 pop하고 갈 수 있는 정점들의 InDegree를 감소시키고, InDegree가 0이면 queue에 넣는다.
3. 1 ~ 2를 반복한다.
시간복잡도
정렬할 때 BFS를 사용 -> O(V + E)
문제
1948 임계경로
1948번: 임계경로
첫째 줄에 도시의 개수 n(1 ≤ n ≤ 10,000)이 주어지고 둘째 줄에는 도로의 개수 m(1 ≤ m ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 도로의 정보가 주어진다. 처음에는 도로의
www.acmicpc.net
코드
#include <bits/stdc++.h>
using namespace std;
class Edge {
public:
int vertex, distance;
explicit Edge(int vertex, int distance) : vertex(vertex), distance(distance) {
}
};
vector<int> topologicalSort(int n, int begin, int end, vector<int> &inDegree, vector<vector<Edge>> &graph) {
queue<Edge> que;
for (int i = 1;i <= n;++i) {
if (inDegree[i] == 0) {
que.emplace(i, 0);
}
}
vector<bool> isFromBegin(n + 1);
isFromBegin[begin] = true;
vector<int> distance(n + 1);
while (!que.empty()) {
Edge now = que.front(); que.pop();
for (Edge &next : graph[now.vertex]) {
if (isFromBegin[now.vertex]) {
distance[next.vertex] = max(distance[next.vertex], now.distance + next.distance);
isFromBegin[next.vertex] = true;
}
inDegree[next.vertex]--;
if (inDegree[next.vertex] == 0) {
que.emplace(next.vertex, distance[next.vertex]);
}
}
}
return distance;
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> inDegree(n + 1);
vector<vector<Edge>> graph(n + 1), rgraph(n + 1);
while (m--) {
int v1, v2, distance;
cin >> v1 >> v2 >> distance;
inDegree[v2]++;
graph[v1].emplace_back(v2, distance);
rgraph[v2].emplace_back(v1, distance);
}
int begin, end;
cin >> begin >> end;
vector<int> distance = topologicalSort(n, begin, end, inDegree, graph);
cout << distance[end] << "\n";
set<pair<int, int>> edges;
queue<Edge> que;
vector<bool> isVisited(n + 1);
que.emplace(end, distance[end]);
while (!que.empty()) {
Edge now = que.front(); que.pop();
if (isVisited[now.vertex]) {
continue;
}
isVisited[now.vertex] = true;
for (Edge &next : rgraph[now.vertex]) {
if (!isVisited[next.vertex] && distance[now.vertex] - distance[next.vertex] == next.distance) {
que.emplace(next.vertex, next.distance);
edges.emplace(min(now.vertex, next.vertex), max(now.vertex, next.vertex));
}
}
}
cout << edges.size() << "\n";
}