입력
첫 번째 줄에는 친구 관계 트리의 정점 개수 N이 주어진다. 단, 2 ≤ N ≤ 1,000,000이며, 각 정점은 1부터 N까지 일련번호로 표현된다. 두 번째 줄부터 N-1개의 줄에는 각 줄마다 친구 관계 트리의 에지 (u, v)를 나타내는 두 정수 u와 v가 하나의 빈칸을 사이에 두고 주어진다. 
출력
주어진 친구 관계 그래프에서 아이디어를 전파하는데 필요한 얼리 아답터의 최소 수를 하나의 정수로 출력한다.
백준1949: 우수마을 문제와 유사하다.
차이점은 우수마을 문제는 우수마을 아닌 마을끼리 인접할 수 있었지만,
사회망서비스 문제는 어댑터가 아닌 친구끼리는 인접할 수 없다.
기본적인 생각은 모든 사람이 어댑터일때와 아닐때를 조사를 해야하지만, 어댑터의 수가 최소가 될 때를 찾는 문제이므로 dp를 이용하여 푼다.
각 서브트리의 루트가 어댑터일때/ 어댑터가 아닐때 재귀함수를 통해
해당 서브트리의 어댑터 수의 최솟값을 return한다.
 루트노드의 각 자식은 루트노드의 상태와 반대값을 무조건 넣어줬는데,
생각해보니 어댑터끼리는 인접해도 상관없으므로,
루트노드가 어댑터라면 자식이 어댑터일때와 어댑터가 아닐때를 비교해
더 작은값을 return하도록 구현하였다.
//해당 노드가 어댑터인지 아닌지로 분기를 나눠 재귀를 하는 함수
int SetLessEarlyAdapter(int node, bool isAdapter) {
	//이미 구한값이면 바로 return
	if (dp[node][isAdapter]) return dp[node][isAdapter];
	//참조자 이용해 값을 바로 변경가능하게 함
	int& ret = dp[node][isAdapter];
	//자식 노드중에
	for (int elem : tree[node]) {
   	   //기본적으로 루트의 상태와 반대값을 자식 노드에 넣어줌
		int tmp = SetLessEarlyAdapter(elem, !isAdapter);
		//어댑터끼리는 둘이 인접해도 되므로 비교해서 더 작은값을 저장
		if (isAdapter) tmp = min(tmp, SetLessEarlyAdapter(elem, isAdapter));
		//자식값들의최소값 다 더해야 한다.
		ret += tmp;
	}
	//자신이 어댑터라면 1 더해줌
	if (isAdapter) ret += 1;
	return ret;
}#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<vector<int>> adj,tree;
vector<bool> visited;
int Nodes;
int dp[1'000'001][2];
void MakeTree(int Node) {
	visited[Node] = true;
	for (int elem : adj[Node]) {
		if (visited[elem]) continue;
		tree[Node].push_back(elem);
		MakeTree(elem);
	}
}
//해당 노드가 어댑터인지 아닌지로 분기를 나눠 재귀를 하는 함수
int SetLessEarlyAdapter(int node, bool isAdapter) {
	//이미 구한값이면 바로 return
	if (dp[node][isAdapter]) return dp[node][isAdapter];
	//참조자 이용해 값을 바로 변경가능하게 함
	int& ret = dp[node][isAdapter];
	//자식 노드중에
	for (int elem : tree[node]) {
		int tmp = SetLessEarlyAdapter(elem, !isAdapter);
		//어댑터아닌사람이 둘이 있을 순없음
		if (isAdapter) tmp = min(tmp, SetLessEarlyAdapter(elem, isAdapter));
		//자식값들의최소값 다 더해줌
		ret += tmp;
	}
	//자신이 어댑터라면 1 더해줌
	if (isAdapter) ret += 1;
	return ret;
}
void Input() {
	int tmpNode1=0, tmpNode2=0;
	cin >> Nodes;
	adj.resize(Nodes + 1);
	tree.resize(Nodes + 1);
	visited.resize(Nodes + 1);
	for (int i = 0; i < Nodes-1; i++) {
		cin >> tmpNode1 >> tmpNode2;
		adj[tmpNode1].push_back(tmpNode2);
		adj[tmpNode2].push_back(tmpNode1);
	}
	MakeTree(tmpNode1);
	cout << min(SetLessEarlyAdapter(tmpNode1, false), SetLessEarlyAdapter(tmpNode1, true));
}
int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	Input();
}바로 인접한 친구끼리는 상태가 무조건 반대여야하는 줄 알고,
SetLessEarlyAdapter함수 내부의 
	//자식 노드중에
	for (int elem : tree[node]) {
		int tmp = SetLessEarlyAdapter(elem, !isAdapter);
		//어댑터아닌사람이 둘이 있을 순없음
		if (isAdapter) tmp = min(tmp, SetLessEarlyAdapter(elem, isAdapter));
		//자식값들의최소값 다 더해줌
		ret += tmp;
	}이 부분을
	//자식 노드중에
	for (int elem : tree[node]) {
		int tmp = SetLessEarlyAdapter(elem, !isAdapter);
		//자식값들의최소값 다 더해줌
		ret += tmp;
	}이렇게 짰었다.
당연히 예제부터 틀렸고 생각해보니
어댑터인 친구가 인접했을 때, 더 어댑터 갯수가 작아지는 반례가 존재했다.