package yukicoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
new Main().solver();
}
void solver() {
Scanner sc = new Scanner(System.in);
long S = sc.nextLong();
Graph g = set_edge(S);
Pair p=ms(g);
System.out.println((p.cardinality+1));
for(int i=0;i
= P) {
g.set_edge(i, j);
}
}
}
return g;
}
// 無向グラフ
class Graph {
ArrayList[] e;
int n;
int[] deg;
boolean[] valid_vertices;//選ぶことのできる頂点
boolean[] choosed_vertices;//選ばれた頂点
Graph(int n) {
this.n = n;
deg = new int[n];
valid_vertices = new boolean[n];
choosed_vertices=new boolean[n];
Arrays.fill(valid_vertices, true);
e = new ArrayList[n];
for (int i = 0; i < n; i++) {
e[i] = new ArrayList<>();
}
}
// 無向グラフの辺a<->を作成
void set_edge(int a, int b) {
if(!e[a].contains((Integer)b)){
e[a].add(b);
e[b].add(a);
deg[a]++;
deg[b]++;
}
}
// 辺a<->bを消去
void delete_undirected_edge(int a, int b) {
e[a].remove((Integer) b);
e[b].remove((Integer) a);
deg[a]--;
deg[b]--;
}
// 頂点vを消去
void delete_vertice(int v) {
while (e[v].size() > 0) {
int u = e[v].get(0);
delete_undirected_edge(u, v);
}
valid_vertices[v] = false;
}
// 頂点vと、vの隣接頂点を消去
void delete_v_with_neighbours(int v) {
while (e[v].size() > 0) {
int u = e[v].get(0);
delete_vertice(u);
}
delete_vertice(v);
}
// deep copy
Graph copy() {
Graph g = new Graph(this.n);
for (int i = 0; i < n; i++) {
g.deg[i] = deg[i];
}
for (int i = 0; i < n; i++) {
g.valid_vertices[i] = valid_vertices[i];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < e[i].size(); j++) {
(g.e[i]).add(e[i].get(j));
}
}
return g;
}
}
Pair ms(Graph g) {
int[] deg = g.deg;
ArrayList[] e = g.e;
boolean[] valid_vertices = g.valid_vertices;
int n = g.n;
int A = -1;// 最も次数の小さい頂点
int B = -1;// Aにつながる頂点のうち最も次数の大きいもの
int deg_me_min = Integer.MAX_VALUE / 4;
int deg_to_max = -Integer.MAX_VALUE / 4;
for (int i = 0; i < n; i++) {
if (!valid_vertices[i])
continue;
if (deg[i] < deg_me_min) {
A = i;
deg_me_min = deg[i];
if (deg_me_min <= 1) {
g.delete_v_with_neighbours(i);
Pair p= ms(g);
p.choosed_vertices[i]=true;
p.cardinality++;
return p;
}
deg_to_max = deg[e[A].get(0)];
B = e[A].get(0);
for (int j = 0; j < e[A].size(); j++) {
int u = e[A].get(j);
if (!valid_vertices[u])
continue;
if (deg[u] > deg_to_max) {
B = u;
deg_to_max = deg[u];
}
}
} else if (deg[i] == deg_me_min) {
for (int j = 0; j < e[A].size(); j++) {
int u = e[A].get(j);
if (!valid_vertices[u])
continue;
if (deg[u] > deg_to_max) {
B = u;
A = i;
deg_to_max = deg[u];
}
}
}
}
// if(deg[A]==2){
//
// }else if(deg[A]==3){
//
// }else{
if (A == -1 && B == -1)
return new Pair(0,new boolean[n]);
Graph g2 = g.copy();
g2.delete_v_with_neighbours(B);
g.delete_vertice(B);
Pair p1=ms(g);
Pair p2=ms(g2);
p2.cardinality++;
p2.choosed_vertices[B]=true;
if(p1.cardinality>p2.cardinality){
return p1;
}else{
return p2;
}
// }
}
class Pair{
int cardinality;
boolean[] choosed_vertices;
Pair(int cardinality,boolean[] choosed_vertices){
this.cardinality=cardinality;
this.choosed_vertices=choosed_vertices;
}
}
}