#include <bits/stdc++.h>
using namespace std;
using lint = long long int;
using pint = pair<int, int>;
using plint = pair<lint, lint>;
struct fast_ios { fast_ios(){ cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(20); }; } fast_ios_;
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)
template<typename T> istream &operator>>(istream &is, vector<T> &vec){ for (auto &v : vec) is >> v; return is; }
template<typename T> ostream &operator<<(ostream &os, const vector<T> &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> ostream &operator<<(ostream &os, const deque<T> &vec){ os << "deq["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> ostream &operator<<(ostream &os, const set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> ostream &operator<<(ostream &os, const unordered_set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> ostream &operator<<(ostream &os, const multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> ostream &operator<<(ostream &os, const unordered_multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; }
template<typename TK, typename TV> ostream &operator<<(ostream &os, const map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template<typename TK, typename TV> ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template<typename T> void ndarray(vector<T> &vec, int len) { vec.resize(len); }
template<typename T, typename... Args> void ndarray(vector<T> &vec, int len, Args... args) { vec.resize(len); for (auto &v : vec) ndarray(v, args...); }
template<typename T> bool mmax(T &m, const T q) { if (m < q) {m = q; return true;} else return false; }
template<typename T> bool mmin(T &m, const T q) { if (m > q) {m = q; return true;} else return false; }
template<typename T1, typename T2> pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first + r.first, l.second + r.second); }
template<typename T1, typename T2> pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first - r.first, l.second - r.second); }
#define dbg(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ") " << __FILE__ << endl;
#define FI first
#define SE second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((lint)(x).size())
#define POW2(n) (1LL << (n))

const string YES = "Yes";
const string NO = "No";
struct UndirectedGraph
{
    using pint = pair<int, int>;

    int V; // 頂点数
    int E; // 辺の数
    int k;
    vector<vector<pint>> to;
    vector<pint> edges;

    vector<int> order, lowlink; // lowlink
    vector<bool> isusedforDFS; // 各辺がDFS木に参加しているか
    vector<bool> is_art; // 各点が関節点か

    vector<vector<int> > bvc_edges; // 二連結成分分解後の全辺の分類

    UndirectedGraph(int V) : V(V), E(0), k(0), to(vector<vector<pint> >(V)){}

    void add_edge(int v1, int v2)
    {
        to[v1].push_back(pint(v2, E));
        to[v2].push_back(pint(v1, E));
        edges.push_back(pint(v1, v2));
        E++;
    }

    vector<int> edge_stack;
    int root_now;
    void _dfs_lowlink(int now, int prev = -1)
    {
        if (prev == -1) root_now = k;
        order[now] = lowlink[now] = k;
        k++;

        for (auto nxt : to[now]) if (nxt.first != prev)
        {
            if (order[nxt.first] < order[now]) edge_stack.push_back(nxt.second);
            if (order[nxt.first] < 0)
            {
                isusedforDFS[nxt.second] = 1;
                _dfs_lowlink(nxt.first, now);
                lowlink[now] = min(lowlink[now], lowlink[nxt.first]);

                if ((order[now] == root_now && order[nxt.first] != root_now+1) || 
                    (order[now] != root_now && lowlink[nxt.first] >= order[now])) is_art[now] = 1;

                if (lowlink[nxt.first] >= order[now])
                {
                    bvc_edges.push_back(vector<int>());
                    while (1)
                    {
                        int edge = edge_stack.back();
                        int v1 = edges[edge].first;
                        int v2 = edges[edge].second;
                        edge_stack.pop_back();
                        bvc_edges.back().push_back(edge);
                        if (min(v1, v2) == min(now, nxt.first) && max(v1, v2) == max(now, nxt.first)) break;
                    }
                }
            } else lowlink[now] = min(lowlink[now], order[nxt.first]);
        }
    }

    void build_lowlink()
    {
        order.assign(V, -1);
        lowlink.assign(V, -1);
        isusedforDFS.assign(E, 0);
        is_art.assign(V, false);
        bvc_edges.clear();
        for (int i = 0; i < V; i++) if (order[i] < 0) _dfs_lowlink(i);
    }
};

int main()
{
    // lint N;
    // cin >> N;
    // lint M;
    // cin >> M;
    // vector<lint> a(M);
    // vector<lint> b(M);
    // REP(i, M){ cin >> a[i]; cin >> b[i]; }

    int V, E;
    cin >> V >> E;
    UndirectedGraph graph(V);
    for (int e = 0; e < E; e++)
    {
        int s, t;
        cin >> s >> t;
        graph.add_edge(s - 1, t - 1);
    }

    int more_six = 0, more_four = 0;
    for (auto v : graph.to)
    {
        // そもそも閉路ダメ
        if (v.size() % 2)
        {
            cout << NO << endl;
            return 0;
        }
        if (v.size() >= 4) more_four++;
        if (v.size() >= 6) more_six++;
    }

    if (more_six or more_four >= 3)
    {
        // 自明に複雑
        cout << YES << endl;
        return 0;
    }
    else if (more_four == 0)
    {
        // ループ
        cout << NO << endl;
        return 0;
    }
    else if (more_four == 1)
    {
        // 八の字
        cout << NO << endl;
        return 0;
    }
    else
    {
        dbg(more_four);
        dbg(more_six);
        // four が3
        int now = 0;
        REP(i, V) if (graph.to[i].size() == 4) now = i;
        queue<int> q;
        vector<int> st(V);
        dbg(now);
        st[now] = true;
        dbg(graph.to[now]);
        for (auto nx : graph.to[now]) q.push(nx.first);
        REP(i, V) if (graph.to[i].size() == 4) st[i] = true;

        while (!q.empty())
        {
            int now = q.front();
            q.pop();
            if (st[now] or graph.to[now].size() == 4) continue;
            st[now] = true;
            for (auto nx : graph.to[now]) q.push(nx.first);
        }

        cout << (accumulate(ALL(st), 0) == V ? NO : YES) << endl;
        return 0;
    }
}


Measured memory_bytes: 6900