친구 관계 그래프가 트리인 경우, 즉 모든 두 정점 사이에 이들을 잇는 경로가 존재하면서 사이클이 존재하지 않는 경우만 고려한다.
사회망 서비스에 속한 사람들은 얼리 어답터이거나 얼리 어답터가 아니다. 얼리 어답터가 아닌 사람들은 자신의 모든 친구들이 얼리 어답터일 때만 이 아이디어를 받아들인다.
지문에서 루트 없는 트리라는 사실을 알려주었다.
- 루트 없는 트리란?
사이클이 존재하지 않는 그래프는 노드 간의 상하 관계가 없을 뿐이지 트리와 같은 형태를 가지고 있는데, 이와 같은 그래프를루트 없는 트리(unrooted tree)
라고 부른다.
루트 없는 트리의 속성
- 정확히 V-1개의 간선이 있다.
- 사이클이 존재하지 않는다.
- 두 정점 사이를 연결하는 단순 경로가 정확히 하나있다.
이 조건들은 모두 동치로, 한 조건이라도 성립할 경우 다른 조건들이 모두 성립한다.
트리의 최소 지배 집합
을 찾는 가장 간단한 방법은 트리의 맨 아래에서부터 시작해서 위로 올라오면서 노드 선택 여부
를 결정한다.리프 노드
는 자기 자신과 부모 노드밖에 지배하지 못하는 반면, 부모 노드
는 그 외의 노드들도 지배할 수 있다. 따라서 리프 노드 대신 그 부모 노드를 선택해서 손해 볼 일은 절대로 없고, 리프 노드는 절대로 선택할 필요가 없다. 대신 그 부모 노드들은 모조리 선택한다. 이것을 정리하면 아래와 같다.visited
배열을 0
으로 초기화한다.NOT_ADOPTER
를 리턴한다.NOT_ADOPTER
가 전달됐다면 현재 노드는 얼리어답터다. 따라서 EARLY_ADOPTER
를 리턴하면서 얼리어답터 인원을 한 명 증가시킨다.EARLY_ADOPTER
라면 현재 노드는 얼리어답터가 아니다. 따라서 NOT_ADOPTER
를 리턴한다.#include <bits/stdc++.h>
#define MAX 1000001
using namespace std;
const int NOT_ADOPTER = 0;
const int EARLY_ADOPTER = 1;
int N;
vector<int> adj[MAX];
int visited[MAX];
int early_adopters;
void init() {
cin >> N;
int u, v;
for(int i = 0; i < N - 1; i++) {
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
}
int dfs(int here) {
visited[here] = true;
int children[2] = {0, 0};
for(int i = 0; i < adj[here].size(); i++) {
int next = adj[here][i];
if(!visited[next]) {
children[dfs(next)]++;
}
}
if(children[NOT_ADOPTER]) {
early_adopters += 1;
return EARLY_ADOPTER;
}
return NOT_ADOPTER;
}
void solve() {
early_adopters = 0;
dfs(1);
cout << early_adopters;
}
int main() {
init();
solve();
return 0;
}
루트 없는 트리
인지 파악하는 습관 들여보자.https://algospot.com/judge/problem/read/GALLERY
https://leetcode.com/problems/longest-path-with-different-adjacent-characters/description/