• 모든 노드의 out degree가 1인 그래프에서 cycle에 속하지 않은 노드의 개수를 구하는 문제이다.

문제 풀이

  • component를 생각하여 방문하지 않은 정점마다 dfs를 돌리면서 cycle을 체크하면 된다. cycle체크는 visited벡터를 0/1/-1(현재 스택에 존재할 때)로 나눠서 -1인 노드를 탐색할 때 cycle이 발견되었다고 처리했다.
소스코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<cstdio>
#include<vector>
#include<stack>
using namespace std;
typedef vector<int> vi;

int main()
{
	int t, n;
	vi res;
	scanf("%d", &t);
	while(t--){
		scanf("%d", &n);
		int cidx=0, gidx=1;
		vi g(n), visited(n, 0), group(n, 0);
		for(int i=0;i<n;i++){
			int t;
			scanf("%d", &t);
			g[i]=--t;
		}

		while(cidx!=n){
			if(visited[cidx]!=0){
				cidx++;
				continue;
			}
			stack<int> st;
			st.push(cidx);
			visited[cidx]=-1;
			while(!st.empty()){
				int next=g[st.top()];
				if(visited[next]==0){
					st.push(next);
					visited[next]=-1;
				}
				else if(visited[next]==-1){
					while(st.top()!=next){
						group[st.top()]=gidx;
						visited[st.top()]=1;
						st.pop();
					}
					group[next]=gidx;
					visited[next]=1;
					st.pop();
				}
				else{
					while(!st.empty()){
						visited[st.top()]=1;
						st.pop();
					}
				}
			}
			cidx++;
		}
		gidx++;
		int nogcnt=0;
		for(int i=0;i<n;i++) if(group[i]==0) nogcnt++;
		res.push_back(nogcnt);
	}
	for(int i=0;i<res.size();i++) printf("%d\n", res[i]);
}

풀고나서

  • cidx를 사용하지 않고 int isempty(vi& visited)라는 함수를 따로 만들어서 components처리하는 두 번째 while문을 while(isempty(visited)!=-1)로 돌렸었는데 이것때문에 시간초과가 나는 것을 어디서 무한루프가 도나 착각했었다.
    priority queue를 쓸 방법을 생각하다가 그냥 인덱스로 while문을 돌리면서 visited의 값을 처음에 확인하면 된다는 것을 깨달았다. 탐색 구현할 때마다 헷갈리지 않게 적어놔야겠다.

  • component 시작점을 찾을 때는 그냥 인덱스로 visited 체크하면서 돌리면 된다

Leave a comment