#include <bits/stdc++.h>
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << " : " << arg1 << " | ";
  __f(comma + 1, args...);
}
void pre() {}
void solve() {}
vector<int> s[400009];
struct UF {
  vector<int> e;
  UF(int n) : e(n, -1) {}
  bool same_set(int a, int b) { return find(a) == find(b); }
  int size(int x) { return -e[find(x)]; }
  int find(int x) { return e[x] < 0 ? x : e[x] = find(e[x]); }
  void join(int a, int b) {
    a = find(a), b = find(b);
    if (a == b) return;
    if (e[a] > e[b]) swap(a, b);
    e[a] += e[b];
    e[b] = a;
  }
};
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cin.exceptions(cin.failbit);
  int n, m;
  cin >> n >> m;
  UF dsu(n + 1);
  int arr[n + 1];
  memset(arr, 0, sizeof(arr));
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    arr[a]++;
    arr[b]++;
    dsu.join(a, b);
  }
  bool flag = true;
  vector<vector<int>> ad(n + 1);
  for (int i = 1; i <= n; i++) {
    ad[dsu.find(i)].push_back(i);
  }
  for (int i = 1; i <= n; i++) {
    if (ad[i].size() > 0) {
      int a = ad[i].size() - 1;
      for (int j = 0; j <= a; j++) {
        if (arr[ad[i][j]] != a) flag = false;
      }
    }
  }
  if (flag == false)
    cout << "NO";
  else
    cout << "YES";
}
