#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
#define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)
#ifdef zerol
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template<template<typename...> class T, typename t, typename... A>
void err(T<t> a, A... x) { for (auto v: a) cout << v << ' '; err(x...); }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }
#else
#define dbg(...)
#endif
// -----------------------------------------------------------------------------

const int N = 500, H = 220, INF = 1E9;
int in[N], out[N];

struct E {
    int to, cp;
    E(int to, int cp): to(to), cp(cp) {}
};

struct Dinic {
    static const int M = 1E5 * 5;
    int m, s, t;
    vector<E> edges;
    vector<int> G[M];
    int d[M];
    int cur[M];

    void init(int n, int s, int t) {
        this->s = s; this->t = t;
        for (int i = 0; i <= n; i++) G[i].clear();
        edges.clear(); m = 0;
    }

    void addedge(int u, int v, int cap) {
        edges.emplace_back(v, cap);
        edges.emplace_back(u, 0);
        G[u].push_back(m++);
        G[v].push_back(m++);
    }

    bool BFS() {
        memset(d, 0, sizeof d);
        queue<int> Q;
        Q.push(s); d[s] = 1;
        while (!Q.empty()) {
            int x = Q.front(); Q.pop();
            for (int& i: G[x]) {
                E &e = edges[i];
                if (!d[e.to] && e.cp > 0) {
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return d[t];
    }

    int DFS(int u, int cp) {
        if (u == t || !cp) return cp;
        int tmp = cp, f;
        for (int& i = cur[u]; i < G[u].size(); i++) {
            E& e = edges[G[u][i]];
            if (d[u] + 1 == d[e.to]) {
                f = DFS(e.to, min(cp, e.cp));
                e.cp -= f;
                edges[G[u][i] ^ 1].cp += f;
                cp -= f;
                if (!cp) break;
            }
        }
        return tmp - cp;
    }

    int go() {
        int flow = 0;
        while (BFS()) {
            memset(cur, 0, sizeof cur);
            flow += DFS(s, INF);
        }
        return flow;
    }
} DC;

void add_edge(int u, int v) {
    dbg(u, v);
    out[u]++; in[v]++;
    DC.addedge(u, v, 1);
}

int fa[N];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
void merge(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy) fa[fx] = fy;
}

const int S = N - 2, T = N - 1;
bool check() {
    int goal = 0;
    FOR (i, 0, N) {
        if (i < H && out[i] > in[i]) {
            goal += out[i] - in[i];
            DC.addedge(S, i, out[i] - in[i]);
        }
        else if (i >= H && in[i] > out[i]) DC.addedge(i, T, in[i] - out[i]);
        else if (in[i] != out[i]) return false;
    }
    if (DC.go() != goal) return false;

    iota(fa, fa + N, 0);
    FOR (u, 0, N) {
        for (int id: DC.G[u]) {
            if (id % 2) continue;
            int v = DC.edges[id].to;
            merge(u, v);
        }
    }
    FOR (i, 0, N)
        if ((in[i] || out[i]) && find(i) != find(S))
            return false;
    return true;
}

int main() {
    DC.init(N, S, T);
    int n, h; cin >> n >> h;
    while (n--) {
        int a, b, c, d; cin >> a >> b >> c >> d;
        int u, v;
        dbg(a, b, c, d);
        if (c == 0) u = a;
        else u = c + H;
        if (d == 0) v = b + H;
        else v = d;
        add_edge(u, v);
    }
    puts(check() ? "YES" : "NO");
}


Measured memory_bytes: 19184