Link

https://www.acmicpc.net/problem/24526

Detail

문제의 핵심은, 그래프 내부에 사이클 이 존재하지 않도록 하는 점이다. 위상정렬에서 아이디어를 착안하여, 리프 노드에서부터 이전 노드들의 outdeg를 줄여나간다.

사이클이 있는 부분이라면, outdeg가 0으로 도달할 수 없게 된다.

Code

#include<bits/stdc++.h>
 
using namespace std;
typedef long long int ll;
 
 
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
 
	int n, m;
	cin >> n >> m;
 
	vector<vector<int>> graph(n + 1);
	vector<vector<int>> reverse_graph(n + 1);
	vector<int> outdeg(n + 1, 0);
 
	// 간선 입력 (중복 간선이 있을 수 있음에 유의)
	for (int i = 0; i < m; i++){
		int u, v;
		cin >> u >> v;
		graph[u].push_back(v);
		reverse_graph[v].push_back(u);
		outdeg[u]++;
	}
 
	queue<int> q;
	vector<bool> safe(n + 1, false);
 
	// 출발 간선이 없는 노드(터미널 노드)는 안전
	for (int i = 1; i <= n; i++){
		if(outdeg[i] == 0){
			q.push(i);
			safe[i] = true;
		}
	}
 
	// 역방향 탐색: 터미널 노드부터 시작하여, 선행 노드들의 outdegree를 줄여나감
	while(not q.empty()){
		int cur = q.front();
		q.pop();
		for(auto prev : reverse_graph[cur]){
			outdeg[prev]--;
			if(outdeg[prev] == 0){
				safe[prev] = true;
				q.push(prev);
			}
		}
	}
 
	// 안전한 노드의 수 계산
	int cnt = 0;
	for(int i = 1; i <= n; i++){
		if(safe[i]) cnt++;
	}
 
	cout << cnt << "\n";
	return 0;
}