#!/usr/bin/env python3 (n, m), reduce, comb = map(int, input().split()), __import__("functools").reduce, __import__("math").comb if not all(c == "0" for c in bin(n)[3:]) or m != (dims := len(bin(n)[3:])) * n // 2: exit(print("no")) edges, node_number, numbers, seen, level, next_level, count = [[] for _ in range(n + 1)], {1: 1}, {1}, {1}, [1], [], 0 for a, b in (map(int, input().split()) for _ in range(m)): (edges[a].append(b), edges[b].append(a)) if not all(len(edges[i]) == dims for i in range(1, n + 1)): exit(print("no")) while level: for curr in level: for neigh in edges[curr]: if neigh not in seen: seen.add(neigh) next_level.append(neigh) count, level, next_level = count + 1, next_level, [] # if len(level) != comb(dims, count): exit(print("no")) # This check IS actually necessary (if the degree check is removed) if count == 1: for i, node in enumerate(level): node_number[node] = 2 << i numbers.add(2 << i) else: for node in level: new = reduce(lambda a, b: a | b, (node_number[neigh] for neigh in edges[node] if neigh in node_number), 0) if new in numbers: exit(print("no")) node_number[node] = new numbers.add(new) print("yes")