• 간선 정보와 루트의 번호만 주어질 때 각 노드들의 부모를 출력하는 문제이다.

문제 풀이

  • 루트노드에서부터 자식들을 bfs로 탐색하면서 부모를 찾아내었다.

  • 아래 코드에서 주석들은 풀고나서 다른 사람들의 코드를 보면서 공부한 것으로, 밑에서 설명하겠다.

소스코드
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include<cstdio>
#include<vector>
#include<deque>
#include<utility>
using namespace std;
typedef pair<int, int> pii;

int main()
{
	int n;
	scanf("%d", &n);
	vector<int> p(n+1, 0);
	p[1]=1;
	deque<pii> d;
	for(int i=0;i<n-1;i++){
		int a, b;
		scanf("%d %d", &a, &b);
		if(p[a]) p[b]=a;
		else if(p[b]) p[a]=b;
		else d.push_back({a, b});
	}
	
	// while(!d.empty()){		//TLE
	// 	deque<pii> d2;
	// 	d2.swap(d);
	// 	for(int i=0;i<d2.size();i++){
	// 		int a=d2[i].first, b=d2[i].second;
	// 		if(p[a]) p[b]=a;
	// 		else if(p[b]) p[a]=b;
	// 		else d.push_back({a, b});
	// 	}
	// }
	while(!d.empty()){		//40ms
        deque<pii> r;
        r.swap(d);
        while(!r.empty()){
            int a=r.front().first,b=r.front().second;r.pop_front();
            if(p[a])p[b]=a;
            else if(p[b])p[a]=b;
            else d.push_front({a,b});
        }
    }
	
	for(int i=2;i<=n;i++) printf("%d\n", p[i]);
	return 0;
}

// #include<cstdio>
// #include<vector>
// #include<queue>
// #include<algorithm>
// #include<utility>
// using namespace std;
// typedef vector<int> vi;
// typedef pair<int, int> pii;

// int main()
// {
// 	int n;
// 	scanf("%d", &n);
// 	vi p(n+1), v(n+1, 0);
// 	vector<pii> e;
// 	for(int i=1;i<n;i++){
// 		int s, z;
// 		scanf("%d %d", &s, &z);
// 		e.push_back(make_pair(s, z));
// 		e.push_back(make_pair(z, s));
// 	}
// 	sort(e.begin(), e.end());
// 	queue<int> q;
// 	auto lb=lower_bound(e.begin(), e.end(), make_pair(1, 1)), ub=upper_bound(e.begin(), e.end(), make_pair(1, n));
// 	v[1]=1;
// 	for(auto it=lb;it!=ub;++it){
// 		p[it->second]=it->first;
// 		q.push(it->second);
// 		v[it->second]=1;
// 	}
// 	while(!q.empty()){
// 		int cur=q.front(), f=1;
// 		lb=lower_bound(e.begin(), e.end(), make_pair(cur, 1)), ub=upper_bound(e.begin(), e.end(), make_pair(cur, n));
// 		for(auto it=lb;it!=ub;++it){
// 			if(v[it->second]==0){
// 				p[it->second]=it->first;
// 				q.push(it->second);
// 				f=0;
// 				v[it->second]=1;
// 			}
// 		}
// 		if(f) q.pop();
// 	}
// 	for(int i=2;i<=n;i++) printf("%d\n", p[i]);
// 	return 0;
// }

풀고나서

  • 내가 처음 제출한 코드는 맨아래 전부 주석처리된 부분으로, 위의 문제 풀이대로 푼 것이다. 풀고나서 isbidip님의 코드를 봤는데 나보다 훨씬 깔끔하고 시간도 적게 들어서 이해한대로 다시 코딩해서 제출했다. 근데 TLE가 떴었다. 보이는 차이는 deque에서 push_front와 push_back의 차이밖에 없었기 때문에 질문을 올렸고, 이건 저 함수들의 실행시간 차이가 아니라 deque가 뒤집히냐 아니냐의 차이였다. TC중에 일자 트리에서 간선이 양끝에서부터 번갈아가며 주어지는 테스트케이스가 많았나보다. 어쨌든 따지고보면 둘 다 O(N^2)이기 떄문에 원래는 TLE가 나야해서 데이터 추가가 요청되었고 현재 내 맨 처음 코드와 두 번째 코드는 재채점 중이다. 첫 번째는 O(NlgN)이기 때문에 맞을거고 두 번째는 아마 틀렸다고 뜰 것 같다.

  • 루트가 주어지기 때문에 루트에서 dfs만 돌려도 다 구할 수 있다. 괜히 어렵게 생각했다. (djm03178님의 코드를 보고 깨달음을 얻었다.)

  • 코드는 깔끔한 게 최고인 것 같다. 앞으로 bits/stdc++.h헤더하고 iostream을 사용해야겠다.

Tags: ,

Categories:

Updated:

Leave a comment