#include <bits/stdc++.h>
using namespace std;
const bool testcases = 0;
template <typename T>
struct number_iterator : iterator<random_access_iterator_tag, T> {
  T u;
  number_iterator(T v) : u(v) {}
  operator T &() { return u; }
  T operator*() const { return u; }
};
template <typename T>
struct number_range {
  T l, r;
  number_range(T b, T e) : l(b), r(e) {}
  number_iterator<T> begin() { return l; }
  number_iterator<T> end() { return r; }
};
template <typename T>
number_range<T> range(T e) {
  return number_range<T>(0, e);
}
template <typename T>
number_range<T> range(T b, T e) {
  if (b > e) return number_range<T>(-b + 1, -e + 1);
  return number_range<T>(b, e);
}
long long int seed;
auto random_address = [] {
  char *p = new char;
  delete p;
  return (uint64_t)p;
};
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() *
            (random_address() | 1));
inline int rnd(int l = 0, int r = INT_MAX) {
  return uniform_int_distribution<int>(l, r)(rng);
}
template <typename T, typename U>
inline bool exist(T cont, U val) {
  return cont.find(val) != cont.end();
}
template <typename T>
bool isPrime(T n) {
  for (T i = 2; i * i <= n; i++)
    if (n % i == 0) return 0;
  return 1;
}
template <typename TAIL>
inline void inp(TAIL &T) {
  cin >> T;
}
template <typename HEAD, typename... TAIL>
inline void inp(HEAD &H, TAIL &...T) {
  cin >> H;
  inp(T...);
}
template <typename T>
inline bool in_range(T a, T l, T r) {
  return (a >= l && a <= r);
}
template <typename T, typename U>
inline istream &operator>>(istream &in, pair<T, U> &a) {
  in >> a.first >> a.second;
  return in;
}
template <typename T>
inline istream &operator>>(istream &in, vector<T> &a) {
  for (auto &x : a) in >> x;
  return in;
}
struct graph {
  int root, size;
  vector<set<int>> adj;
  vector<bool> vis;
  graph(int n = -1) {
    if (~n) init(size = n);
  }
  void init(int n) {
    adj.resize(n + 1);
    vis.assign(n + 1, 0);
    root = 1;
  }
  void make_edge(int u, int v, bool directed = 0) {
    adj[u].insert(v);
    if (!directed) adj[v].insert(u);
  }
  bool is_edge(int u, int v) { return adj[u].find(v) != adj[u].end(); }
  void dfs(int u) {
    if (!vis[u]) {
      vis[u] = 1;
      for (int v : adj[u]) dfs(v);
    }
  }
  bool check_graph_connected_dfs() {
    vis.assign(size, 0);
    dfs(root);
    return find(vis.begin(), vis.end(), 0) == vis.end();
  }
  int cc_count() {
    int cc_count = 0;
    vis.assign(size + 1, 0);
    for (int i : range(size)) {
      if (!vis[i + 1]) {
        cc_count++;
        dfs(i + 1);
      }
    }
    return cc_count;
  }
};
struct dsu {
  vector<int> parent;
  int count = 0;
  dsu(int n = -1) {
    if (~n) init(n);
  }
  void init(int n) {
    parent.assign(n + 1, -1);
    count = n;
  }
  int find(int x) { return parent[x] < 0 ? x : parent[x] = find(parent[x]); }
  int size(int x) { return -parent[x]; }
  bool merge(int x, int y, bool choice = 0) {
    x = find(x);
    y = find(y);
    if (x == y) return 0;
    if (!choice && size(x) < size(y)) swap(x, y);
    parent[x] += parent[y];
    parent[y] = x;
    count--;
    return 1;
  }
};
string to_string(const dsu &a) { return ""; }
int main() {
  std::chrono::time_point<std::chrono::high_resolution_clock> start_time,
      end_time;
  start_time = std::chrono::high_resolution_clock::now();
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n, m;
  int __T__ = 1;
  if (testcases) cin >> __T__;
  while (__T__--) {
    cin >> n >> m;
    graph g(n);
    dsu a(n);
    int u, v;
    while (m--) {
      cin >> u >> v;
      a.merge(u, v);
      g.make_edge(u, v);
    }
    map<int, vector<int>> mp;
    for (int i = 0; i < n; i++) mp[a.find(i + 1)].push_back(i + 1);
    bool f = 1;
    for (const pair<int, vector<int>> &p : mp) {
      n = p.second.size();
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
          if (i == j) continue;
          if (!g.is_edge(p.second[i], p.second[j])) {
            f = 0;
            break;
          }
        }
        if (!f) break;
      }
      if (!f) break;
    }
    1729;
    1729;
    puts(f ? "YES" : "NO");
    108;
  }
  end_time = std::chrono::high_resolution_clock::now();
  long long int elapsed_time =
      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
                                                            start_time)
          .count();
  42;
  if (elapsed_time < 10000)
    42;
  else
    42;
  return 0;
}
