#nullable enable

using System.Numerics;

void Run() => Out(Solve() ? "YES" : "NO");

bool Solve()
{
    var m = Int();
    var tz = m.Repeat(() => (Int(), Int(), Int()));
    if (tz.Distinct().Count() < m) return false;
    var mz = new Dictionary<(int, int), HashSet<int>>();
    for (var i = 0; i < m; i++)
    {
        var (a, b, c) = tz[i];
        var pz = new[]{ (a, b), (b, c), (a, c) };
        foreach (var p in pz)
        {
            if (!mz.ContainsKey(p)) mz[p] = new();
            var h = mz[p];
            if (h.Count == 2) return false;
            h.Add(i);
        }
    }
    var ez = new HashSet<(int, int)>();
    foreach (var (u, v) in mz.Keys)
    {
        ez.Add((u, v));
        ez.Add((v, u));
    }
    var dz = new int[m];
    var q = new Queue<int>();
    for (var si = 0; si < m; si++)
    {
        if (dz[si] >= 1) continue;
        q.Enqueue(si);
        dz[si] = 1;
        while (q.Count > 0)
        {
            var i = q.Dequeue();
            var (a, b, c) = tz[i];
            if (!ez.Contains((a, b)) || !ez.Contains((b, c)) || !ez.Contains((c, a))) (b, c) = (c, b);
            if (!ez.Contains((a, b)) || !ez.Contains((b, c)) || !ez.Contains((c, a))) return false;
            dz[i]++;
            var pz = new[] { (a, b), (b, c), (c, a) };
            foreach (var (ou, ov) in pz)
            {
                var (u, v) = (ou, ov);
                ez.Remove((u, v));
                if (u > v) (u, v) = (v, u);
                foreach (var j in mz[(u, v)]) if (dz[j] == 0) 
                {
                    q.Enqueue(j);
                    dz[j]++;
                }
            }
        }
    }
    return true;
}

#region
AtCoderIO _io_;
var _backend_ = new StandardIOBackend();
_io_ = new(){ Backend = _backend_ };
Run();
_backend_.Flush();

string String() => _io_.Next();
int Int() => int.Parse(String());
void Out(object? x, string? sep = null) => _io_.Out(x, sep);

class AtCoderIO
{
    public required StandardIOBackend Backend { get; init; }

    Memory<string> _input = Array.Empty<string>();
    int _iter = 0;
    public string Next()
    {
        while (_iter >= _input.Length) (_input, _iter) = (Backend.ReadLine().Split(' '), 0);
        return _input.Span[_iter++];
    }

    public void Out(object? x, string? separator = null)
    {
        if (x == null) return;
        separator ??= Environment.NewLine;
        if (x is System.Collections.IEnumerable a and not string)
        {
            var objects = a.Cast<object>();
            if (separator == Environment.NewLine && !objects.Any()) return;
            x = string.Join(separator, objects);
        }
        Backend.WriteLine(x);
    }
}

class StandardIOBackend
{
    readonly StreamReader _sr = new(Console.OpenStandardInput());
    readonly StreamWriter _sw = new(Console.OpenStandardOutput()) { AutoFlush = false };
    public string ReadLine() => _sr.ReadLine()!;
    public void WriteLine(object? value) => _sw.WriteLine(value);
    public void Flush() => _sw.Flush();
}
#endregion

static class Extensions
{
    public static T[] Repeat<T>(this int time, Func<T> F) => Enumerable.Range(0, time).Select(_ => F()).ToArray();
}