Problem:
Score : 200 points

Problem Statement

There are four towns, numbered 1,2,3 and 4.
Also, there are three roads. The i-th road connects different towns a_i and b_i bidirectionally.
No two roads connect the same pair of towns. Other than these roads, there is no way to travel between these towns, but any town can be reached from any other town using these roads.

Determine if we can visit all the towns by traversing each of the roads exactly once.

Constraints

1 \leq a_i,b_i \leq 4(1\leq i\leq 3)

a_i and b_i are different. (1\leq i\leq 3)

No two roads connect the same pair of towns.

Any town can be reached from any other town using the roads.

Input

Input is given from Standard Input in the following format:

a_1 b_1
a_2 b_2
a_3 b_3

Output

If we can visit all the towns by traversing each of the roads exactly once, print YES; otherwise, print NO.

Sample Input 1

4 2
1 3
2 3

Sample Output 1

YES

We can visit all the towns in the order 1,3,2,4.

Sample Input 2

3 2
2 4
1 2

Sample Output 2

NO

Sample Input 3

2 1
3 2
4 3

Sample Output 3

YES

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
#if !DEBUG
    using System.IO;
#endif


public class Program {
    public static void Main() {
        #region SetAutoFlushIsFalse
#if !DEBUG
        var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
        Console.SetOut(sw);
#endif
        #endregion

        var abs = ReadLib.ReadNTimesAsIntArray(3);
        var graph = Enumerable.Range(1, 4).ToDictionary(i => i, i => new List<int>());
        var unionFind = new UnionFind(4, 1);
        foreach (var ab in abs) {
            unionFind.Unite(ab[0], ab[1]);
        }

        var isOk = Enumerable.Range(1, 4).Select(i => unionFind.GetRoot(i)).Distinct().Count() == 1;
        Console.WriteLine(isOk ? "YES" : "NO");

        #region Flush
#if !DEBUG
        Console.Out.Flush();
        sw.Close();
#endif
        #endregion
    }
}


static class Calculation {
    internal static bool Calc(int n, string[] words) {
        if (words.Length != words.Distinct().Count()) {
            return false;
        }

        for (int i = 1; i < n; i++) {
            var prevC = words[i - 1].Last();
            var c = words[i].First();
            if (prevC != c) {
                return false;
            }
        }
        return true;
    }
}


/// <summary>UnionFind木</summary>
public class UnionFind {
    Dictionary<int, int> nodeToRoot;
    Dictionary<int, int> rank; // その根が配下に何個nodeがぶら下がっているか

    public UnionFind(int n, int startAt = 0) {
        nodeToRoot = Enumerable.Range(startAt, n).ToDictionary(i => i, i => i);    // n個根を作る
        rank = Enumerable.Range(startAt, n).ToDictionary(i => i, i => 0);
    }

    /// <summary>根を得る</summary>
    public int GetRoot(int x) {
        if (nodeToRoot[x] == x) { // 渡されたノードが根
            return x;
        }
        nodeToRoot[x] = GetRoot(nodeToRoot[x]);  // parentの根を得てset。調べるたびに最適化。

        return nodeToRoot[x];
    }

    /// <summary>xとyの木を併合 => 根を同一にする</summary>
   　public void Unite(int x, int y) {
        var rootX = GetRoot(x);
        var rootY = GetRoot(y);

        if (rootX == rootY) {
            return; // pass
        }

        if (rank[x] > rank[y]) {    // yをxへ併合
            nodeToRoot[y] = nodeToRoot[x];
            return;
        } else {
            nodeToRoot[x] = nodeToRoot[y];

            if (rank[x] == rank[y]) {
                rank[y]++;  // yの下に配下が1つ追加される。
            }

            return;
        }
    }

    public bool AreSameRoot(int x, int y) {
        return GetRoot(x) == GetRoot(y);
    }
}

/// <summary>根付き木</summary>
public class RootedTree {
    public int Id { get; }
    public int Parent { get; }
    public int Depth { get; set; }
    int[] Childs { get; }

    public RootedTree(int id, int parent, int[] childs) {
        this.Id = id;
        this.Parent = parent;
        this.Childs = childs;
    }
}



static class Quick {

    internal static void Calculate(int[] ts) {
        QuickSort(ts, 0, ts.Count() - 1);
    }

    private static void QuickSort(int[] ts, int p, int r) {
        if (p < r) {
            var q = Partition(ts, p, r);
            QuickSort(ts, p, q - 1);
            QuickSort(ts, q + 1, r);
        }
    }

    public static int Partition(int[] sArr, int p, int r) {
        var x = sArr[r];
        var i = p - 1;
        for (int j = p; j < r; j++) {
            if (sArr[j] <= x) {
                i++;
                sArr.Swap(i, j);
            }
        }
        sArr.Swap(i + 1, r);
        return i + 1;
    }

}

static class ReadLib {
    public static long ReadAsLong() {
        return long.Parse(Console.ReadLine());
    }

    public static int ReadAsInt() {
        return int.Parse(Console.ReadLine());
    }

    public static int[] ReadAsIntArray(int step = 0) {
        return Console.ReadLine().Split(' ').Select(s => int.Parse(s) + step).ToArray();
    }

    public static long[] ReadAsLongArray(int step = 0) {
        return Console.ReadLine().Split(' ').Select(s => long.Parse(s) + step).ToArray();
    }

    public static ulong[] ReadAsULongArray() {
        return Console.ReadLine().Split(' ').Select(s => ulong.Parse(s)).ToArray();
    }

    public static string[] ReadAsStringArray() {
        return Console.ReadLine().Split(' ');
    }

    public static int[] ReadNTimesAsInt(int n, int step = 0) {
        return Enumerable.Range(1, n).Select(s => int.Parse(Console.ReadLine()) + step).ToArray();
    }


    public static long[] ReadNTimesAsLong(int n, int step = 0) {
        return Enumerable.Range(1, n).Select(s => long.Parse(Console.ReadLine()) + step).ToArray();
    }

    public static int[][] ReadNTimesAsIntArray(int n, int step = 0) {
        return Enumerable.Range(1, n).Select(s => ReadAsIntArray(step)).ToArray();
    }

    public static string[] ReadNTimesAsString(int n) {
        return Enumerable.Range(1, n).Select(s => Console.ReadLine()).ToArray();
    }

}

static class WriteLib {
    public static void Write<T>(IEnumerable<T> ts) {
        ts.ToList().ForEach(s => Console.WriteLine(s));
    }
}

static class MyMath {
    /// <summary>階乗</summary>
    public static long Factorial(int n) {
        if (n == 0) {
            return 1;
        }

        return Permutation(n, 0);
    }

    public static long Permutation(int n, int k) {
        return Enumerable.Range(0, n - k).Select(i => n - i).Aggregate(1, (b, i) => b * i);
    }

    #region FullPower
    /// <summary>総乗、π</summary>
    public static long FullPower(IEnumerable<long> vs) {
        return vs.Aggregate(1L, (a, b) => a * b);
    }

    public static long FullPower(IEnumerable<int> vs) {
        return vs.Aggregate(1L, (a, b) => a * b);
    }
    #endregion

    /// <summary>最大公約数</summary>
    public static long Gcd(long item1, long item2) {
        var a = Math.Max(item1, item2);
        var b = Math.Min(item1, item2);

        while (true) {
            long mod;
            Math.DivRem(a, b, out mod);
            if (mod == 0) {
                break;
            }

            a = b;
            b = mod;
        }
        return b;
    }

    /// <summary>約分。最大公約数で割ったものを返す。</summary>
    public static Tuple<long, long> DeviedByGcd(long item1, long item2) {
        var gcd = Gcd(item1, item2);
        return new Tuple<long, long>(item1 / gcd, item2 / gcd);
    }

    public static long Lcm(int item1, int item2) {
        return Math.BigMul(item1, item2) / Gcd(item1, item2);
    }

    public static ModCombination ModCombination(int maxN, int mod = 1000000007) {
        return new ModCombination(maxN, mod);
    }

    /// <summary>a^n mod</summary>
    public static int ModPow(int a, int n, int mod = 1000000007) {
        var res = 1;
        while (n > 0) {
            if ((n & 1) == 1) {
                res = (int)(Math.BigMul(res % mod, a) % mod);    // resにaをかける
            }
            a = (int)(Math.Pow(a % mod, 2) % mod);    // 次のaはa^2
            n >>= 1;
        }

        return res;
    }
}

static class MyMethod {
    /// <summary>数え上げて、key, 出現回数に変換</summary>
    public static Dictionary<T, int> CountUp<T>(IEnumerable<T> str) {
        return
            str
            .GroupBy(c => c)
            .Select(g => new KeyValuePair<T, int>(g.Key, g.Count()))
            .ToDictionary(e => e.Key, e => e.Value);
    }

    /// <summary>計数ソート</summary>
    public static int[] CountingSort(int[] aArr, int k) {
        int[] b, c;
        var n = aArr.Length;
        b = new int[n];
        c = Enumerable.Repeat(0, k + 1).ToArray();


        for (int i = 0; i < n; i++) {
            c[aArr[i]]++;
        }

        for (int i = 1; i <= k; i++) {
            c[i] += c[i - 1];
        }

        for (int i = n - 1; i >= 0; i--) {
            b[c[aArr[i]] - 1] = aArr[i];
            c[aArr[i]]--;
        }

        return b;
    }
}

/// <summary>無向グラフ</summary>
class UndirectedGraph {
    public Dictionary<int, List<int>> Graph { get; }

    /// <param name="graphArr">point1 to point2</param>
    /// <param name="n">グラフの全要素数</param>
    public UndirectedGraph(int[][] graphArr, int n) {
        Graph = new Dictionary<int, List<int>>();

        for (int i = 1; i <= n; i++) {
            Graph.Add(i, new List<int>());
        }

        foreach (var arr in graphArr) {
            Graph[arr[0]].Add(arr[1]);
            Graph[arr[1]].Add(arr[0]);
        }
    }
}
/// <summary>DeepCopyするクラス</summary>
class DeepCopier {
    BinaryFormatter b = new BinaryFormatter();
    public T DeepCopy<T>(T obj) {
        T result;
        using (var mem = new MemoryStream()) {
            b.Serialize(mem, obj); //  binaryFormatterによりobjをmemにserial化して書き出す
            mem.Position = 0; // memのpotisionを先頭に戻す
            result = (T)b.Deserialize(mem); // memの内容を読み取る。
        }
        return result;
    }
}

static class MergeSort {
    public static long[] Sort(long[] arr) {
        return Sort(arr, 0, arr.Count());
    }

    // rightは+1されていることに注意
    private static long[] Merge(long[] sArr, int left, int mid, int right) {
        var n1 = mid - left;
        var n2 = right - mid;

        var lArr = new long[n1 + 1];
        var rArr = new long[n2 + 1];

        for (int i = 0; i < n1; i++) {
            lArr[i] = sArr[left + i];
        }
        lArr[n1] = int.MaxValue;

        for (int i = 0; i < n2; i++) {
            rArr[i] = sArr[mid + i];
        }
        rArr[n2] = int.MaxValue;

        int l = 0, r = 0;
        for (int k = left; k < right; k++) {
            if (lArr[l] <= rArr[r]) {
                sArr[k] = lArr[l];
                l++;
            } else {
                sArr[k] = rArr[r];
                r++;
            }
        }
        return sArr; // 要素数はright - left
    }

    private static long[] Sort(long[] sArr, int left, int right) {
        if (left + 1 < right) {
            var mid = (left + right) / 2;
            sArr = Sort(sArr, left, mid);
            sArr = Sort(sArr, mid, right);
            sArr = Merge(sArr, left, mid, right);
        }
        return sArr;
    }
}

/// <summary>あまりを計算するためのintのラッパー</summary>
struct ModInt {
    int Value { get; }
    int Mod { get; }

    public override string ToString() {
        return Value.ToString();
    }

    public static explicit operator ModInt(long value) {
        return new ModInt(value);
    }

    public ModInt(long value, int mod = 1000000007) {
        this.Value = (int)(value % mod);
        this.Mod = mod;
    }

    public static explicit operator int(ModInt modInt) {
        return modInt.Value;
    }

    private static void CheckNotEqualMod(ModInt item1, ModInt item2) {
        if (item1.Mod != item2.Mod) {
            throw new Exception("mod not equal");
        }
    }

    public static ModInt operator +(ModInt item1, ModInt item2) {
        CheckNotEqualMod(item1, item2);
        long value = item1.Value + item2.Value;
        return new ModInt(value, item1.Mod);
    }

    public static ModInt operator *(ModInt item1, ModInt item2) {
        CheckNotEqualMod(item1, item2);
        long value = Math.BigMul(item1.Value, item2.Value);
        return new ModInt(value, item1.Mod);
    }

    public static ModInt operator -(ModInt item1, ModInt item2) {
        CheckNotEqualMod(item1, item2);
        long value = item1.Value - item2.Value;
        if (value < 0) {
            value += item1.Mod;
        }
        return new ModInt(value, item1.Mod);
    }

    public static ModInt operator +(ModInt item1, int item2) {
        return item1 + new ModInt(item2, item1.Mod);
    }

    public static ModInt operator *(ModInt item1, int item2) {
        return item1 * new ModInt(item2, item1.Mod);
    }

    public static ModInt operator -(ModInt item1, int item2) {
        return item1 - new ModInt(item2, item1.Mod);
    }


    public override int GetHashCode() {
        return this.Value;
    }

    public override bool Equals(object obj) {
        if (obj == null || this.GetType() != obj.GetType()) {
            return false;
        }

        var modIntObj = (ModInt)obj;
        return modIntObj.Value == this.Value;
    }

    public static bool operator ==(ModInt item1, ModInt item2) {
        return item1.Value == item2.Value;
    }

    public static bool operator !=(ModInt item1, ModInt item2) {
        return !(item1 == item2);
    }

    public static bool operator ==(ModInt item1, int item2) {
        return item1.Value == item2;
    }

    public static bool operator !=(ModInt item1, int item2) {
        return !(item1.Value == item2);
    }

    public static bool operator >=(ModInt item1, ModInt item2) {
        return item1.Value >= item2.Value;
    }

    public static bool operator <=(ModInt item1, ModInt item2) {
        return item1.Value <= item2.Value;
    }

    public static bool operator >=(ModInt item1, int item2) {
        return item1.Value >= item2;
    }

    public static bool operator <=(ModInt item1, int item2) {
        return item1.Value <= item2;
    }

    public static bool operator >(ModInt item1, ModInt item2) {
        return item1.Value > item2.Value;
    }

    public static bool operator <(ModInt item1, ModInt item2) {
        return item1.Value < item2.Value;
    }

    public static bool operator >(ModInt item1, int item2) {
        return item1.Value >= item2;
    }

    public static bool operator <(ModInt item1, int item2) {
        return item1.Value <= item2;
    }
}

/// <summary>組み合わせ</summary>
class ModCombination {
    private int mod;
    private int[] fac;
    private int[] finv;
    private int[] inv;

    public ModCombination(int max, int mod = 1000000007) {
        this.mod = mod;
        fac = new int[max]; // modが法のn!の列

        inv = new int[max]; // indexの逆元の列
        finv = new int[max]; // modを法とした、invの累積の累積

        fac[0] = 1; fac[1] = 1;
        finv[0] = 1; finv[1] = 1;
        inv[1] = 1;

        for (int i = 2; i < max; i++) {
            fac[i] = (int)(Math.BigMul(fac[i - 1], i) % mod);  // factorを求める
            var s = Math.BigMul(inv[mod % i], mod / i) % mod;
            inv[i] = (int)(mod - s);　 // iに対する逆元を求める
            finv[i] = (int)(Math.BigMul(finv[i - 1], inv[i]) % mod);
        }
    }
    /// <summary>nCk</summary>
    public int Calculation(int n, int k) {
        if (n < k) return 0;
        if (n < 0 || k < 0) return 0;

        return (int)(Math.BigMul(fac[n], (int)(Math.BigMul(finv[k], finv[n - k]) % mod)) % mod);
    }
}

/// <summary>拡張メソッドs</summary>
static class Extention {
    /// <summary>iとjを入れ替える</summary>
    public static void Swap<T>(this T[] arr, int i, int j) {
        var buf = arr[i];
        arr[i] = arr[j];
        arr[j] = buf;
    }

    /// <summary>
    /// partition。末尾sArr[r]を基準として、左に基準より小さい数、右に基準より大きい数が存在するように配列を並び替える。
    /// </summary>
    /// <param name="sArr"></param>
    /// <param name="p">partitionの先頭の添字</param>
    /// <param name="r">partitionの末尾の添字</param>
    /// <returns>partitionの基準が存在する添字</returns>
    public static int Partition(this int[] sArr, int p, int r) {
        var x = sArr[r];
        var i = p - 1;
        for (int j = p; j < r; j++) {
            if (sArr[j] <= x) {
                i++;
                sArr.Swap(i, j);
            }
        }
        sArr.Swap(i + 1, r);
        return i + 1;
    }

    /// <summary>深いコピーをする</summary>
    public static T DeepCopy<T>(this T obj) {
        T result;
        var b = new BinaryFormatter();
        using (var mem = new MemoryStream()) {
            b.Serialize(mem, obj); //  binaryFormatterによりobjをmemにserial化して書き出す
            mem.Position = 0; // memのpotisionを先頭に戻す
            result = (T)b.Deserialize(mem); // memの内容を読み取る。
        }
        return result;
    }

    public static string Left(this string str, int length) {
        return str.Substring(0, length);
    }

    public static string Right(this string str, int length) {
        return str.Substring(str.Length - length, length);
    }
}