# Группа солдат-новобранцев прибыла в армейскую часть. После знакомства с прапорщиком
# стало очевидно, что от работ на кухне по очистке картофеля спасти солдат может только чудо.
# Прапорщик, будучи не в состоянии запомнить фамилии, пронумеровал новобранцев от 1 до N.
# После этого он велел им построиться по росту (начиная с самого высокого).
# С этой несложной задачей могут справиться даже совсем необученные новобранцы,
# да вот беда, прапорщик уверил себя, что знает про некоторых солдат,
# кто из них кого выше, и это далеко не всегда соответствует истине.
# После трех дней обучения новобранцам удалось выяснить, что знает
# (а точнее, думает, что знает) прапорщик. Помогите им, используя эти знания,
# построиться так, чтобы товарищ прапорщик остался доволен.
# Формат входных данных
# Сначала на вход программы поступают числа N и M (1 < N <= 100, 1 <= M <= 5000) –
# количество солдат в роте и количество пар солдат, про которых прапорщик знает,
# кто из них выше. Далее идут эти пары чисел A и B по одной на строке (1 <= A,B <= N),
# что означает, что, по мнению прапорщика, солдат A выше, чем B.
# Не гарантируется, что все пары чисел во входных данных различны.
# Формат выходных данных
# В первой строке выведите "Yes" (если можно построиться так,
# чтобы прапорщик остался доволен) или "No" (если нет).

from collections import defaultdict

# Топологическая сортировка возможна в том случае,
# если оргграф не содержит циклов.


class Graph():
    # Данный класс предназначен для представления графа
    # в виде списка смежности вершин. Содержит функции,
    # позволяющие определить наличие в нем цикла.

    def __init__(self, vertices):
        self.graph = defaultdict(list)
        self.V = vertices

    def addEdge(self, u, v):
        """Функция добавляет ребро (u, v) в граф."""
        self.graph[u].append(v)

    def isCyclicUtil(self, v, visited, recStack):
        """Вспомогательная функция для проверки наличия цикла в графе."""

        # Добавляем текущую вершину в посещенные
        # и в стэк для рекурсии.
        visited[v] = True
        recStack[v] = True

        # Перебираем все смежные вершины.
        # Если какую-то из них уже посещали,
        # и она в стэке, то граф содержит цикл.
        for neighbour in self.graph[v]:
            if visited[neighbour] == False:
                if self.isCyclicUtil(neighbour, visited, recStack) == True:
                    return True
            elif recStack[neighbour] == True:
                return True

        # До завершения функции необходимо убрать вершину из стэка.
        recStack[v] = False
        return False

    def isCyclic(self):
        """Функция возвращает True, если граф содержит цикл, иначе - False."""
        # Нумерация начинается с 1, поэтому везде делаем поправку,
        # чтобы не учитывать вершину 0.
        visited = [False] * (self.V + 1)
        recStack = [False] * (self.V + 1)
        for node in range(1, self.V + 1):
            if visited[node] == False:
                if self.isCyclicUtil(node, visited, recStack) == True:
                    return True
        return False


# Считываем количество вершин и ребер в графе:
n, m = (int(s) for s in input().split())

# Создаем экземпляр графа с n вершинами
g = Graph(n)

# Создаем множество ребер для проверки наличия
# обратных ребер уже на этапе считывания графа.
edges = set()

for i in range(m):
    a, b = (int(s) for s in input().split())
    if (b, a) in edges:  # Если ранее встречалось обратное ребро,
        print('No')  # построение невозможно.
        exit()  # Завершаем программу.
    edges.add((a, b))  # Добавляем ребро в множество
    g.addEdge(a, b)

if g.isCyclic() == 1:
    print("No")
else:
    print("Yes")
