#include using namespace std; template struct graph { struct edge { int from, to; T cost; }; vector edges; vector> g; int n; graph(int n) : n(n) { g.resize(n); } virtual void add(int from, int to, T cost) = 0; }; template struct undirected_graph : graph { using graph::edges; using graph::g; using graph::n; undirected_graph(int n) : graph(n) { } void add(int from, int to, T cost = 1) { assert(0 <= from && from < n && 0 <= to && to < n); g[from].emplace_back(edges.size()); g[to].emplace_back(edges.size()); edges.push_back({from, to, cost}); } }; template vector dijkstra(const graph &g, int start) { assert(0 <= start && start < g.n); vector dist(g.n, numeric_limits::max()); priority_queue, vector>, greater>> s; dist[start] = 0; s.emplace(dist[start], start); while (!s.empty()) { T expected = s.top().first; int i = s.top().second; s.pop(); if (expected != dist[i]) { continue; } for (int id : g.g[i]) { auto &e = g.edges[id]; int to = e.from ^ e.to ^ i; if (dist[i] + e.cost < dist[to]) { dist[to] = dist[i] + e.cost; s.emplace(dist[to], to); } } } return dist; } int main() { int n, m; cin >> n >> m; undirected_graph g(n); for (int i = 0; i < m; i++) { int from, to; cin >> from >> to; g.add(from, to); } auto d = dijkstra(g, g.edges[0].from); for (auto &e : g.edges) { if (d[e.from] == numeric_limits::max()) { cout << "NO" << endl; return 0; } } int puni = 0; for (auto &i : g.g) { if (i.size() & 1) { puni++; } } cout << (puni <= 2 ? "YES" : "NO") << endl; return 0; }