Problem: 2063C - Remove Exactly Two
Language: C# 10

Previous submission (verdict: Wrong answer on test 26):
using System;
using System.Collections.Generic;
using System.Linq;

namespace task2063c;

class Node
{
    readonly List<Node> _neighbours = new();

    //public int Count => _children.Count;
    public int Connections => _neighbours.Count;

    public void AddNeighbour(Node n) => _neighbours.Add(n);

    public void Cut() => _neighbours.ForEach(n => n.RemoveNeighbour(this));

    private void RemoveNeighbour(Node node) => _neighbours.Remove(node);

    public int NumSingleNeigbours => _neighbours.Count(n => n.Connections == 1);
}

class Tree
{
    readonly Dictionary<int, Node> _nodes = new();
    readonly int _count;
    public int Parts { get; private set; }


    public Tree(int vertices)
    {
        _count = vertices;
        Parts = 1;
    }

    public void ReadFromInput()
    {
        for(var i=0; i<_count-1; ++i)
        {
            var str = Console.ReadLine();
            var numbers = str.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
            if(numbers.Length != 2)
                throw new InvalidOperationException($"invalid format for node: {str}");

            var n1 = numbers[0];
            var n2 = numbers[1];

            if(!_nodes.TryGetValue(n1, out var node1))
                _nodes[n1] = node1 = new Node();

            if(!_nodes.TryGetValue(n2, out var node2))
                _nodes[n2] = node2 = new Node();

            node1.AddNeighbour(node2);
            node2.AddNeighbour(node1);
        }
    }

    void CutNode(KeyValuePair<int, Node> kv)
    {
        Parts += (kv.Value.Connections - 1);
        kv.Value.Cut();
        _nodes.Remove(kv.Key);
    }

    public void CutMax(bool rank)
    {
        if(!_nodes.Any())
            return;

        var maxNodeKv = _nodes.Max(Comparer<KeyValuePair<int, Node>>.Create((kv1, kv2) => kv1.Value.Connections.CompareTo(kv2.Value.Connections)));
        if(rank)
        {
            var comp = Comparer<KeyValuePair<int, Node>>.Create((kv1, kv2) => kv1.Value.NumSingleNeigbours.CompareTo(kv2.Value.NumSingleNeigbours));
            var connections = maxNodeKv.Value.Connections;
            maxNodeKv = _nodes.Where(kv => kv.Value.Connections == connections).Max(comp);
        }

        CutNode(maxNodeKv);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        var numTestsw = int.Parse(Console.ReadLine());
        var results = new List<int>();

        for(var i=0; i<numTestsw; ++i)
        {
            var tree = new Tree(int.Parse(Console.ReadLine()));
            tree.ReadFromInput();

            tree.CutMax(true);
            tree.CutMax(false);

            results.Add(tree.Parts);
        }

        foreach(var n in results)
            Console.WriteLine(n);
    }
}



Submission (verdict: Accepted):
using System;
using System.Collections.Generic;
using System.Linq;

namespace task2063c;

class Node
{
    readonly List<Node> _neighbours = new();

    //public int Count => _children.Count;
    public int Connections => _neighbours.Count;

    public void AddNeighbour(Node n) => _neighbours.Add(n);

    public void Cut() => _neighbours.ForEach(n => n.RemoveNeighbour(this));

    private void RemoveNeighbour(Node node) => _neighbours.Remove(node);

    public int NumBigNeigbours => _neighbours.Count(n => n.Connections == Connections);
}

class Tree
{
    readonly Dictionary<int, Node> _nodes = new();
    readonly int _count;
    public int Parts { get; private set; }


    public Tree(int vertices)
    {
        _count = vertices;
        Parts = 1;
    }

    public void ReadFromInput()
    {
        for(var i=0; i<_count-1; ++i)
        {
            var str = Console.ReadLine();
            var numbers = str.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
            if(numbers.Length != 2)
                throw new InvalidOperationException($"invalid format for node: {str}");

            var n1 = numbers[0];
            var n2 = numbers[1];

            if(!_nodes.TryGetValue(n1, out var node1))
                _nodes[n1] = node1 = new Node();

            if(!_nodes.TryGetValue(n2, out var node2))
                _nodes[n2] = node2 = new Node();

            node1.AddNeighbour(node2);
            node2.AddNeighbour(node1);
        }
    }

    void CutNode(KeyValuePair<int, Node> kv)
    {
        Parts += (kv.Value.Connections - 1);
        kv.Value.Cut();
        _nodes.Remove(kv.Key);
    }

    public void CutMax(bool rank)
    {
        if(!_nodes.Any())
            return;

        var maxNodeKv = _nodes.Max(Comparer<KeyValuePair<int, Node>>.Create((kv1, kv2) => kv1.Value.Connections.CompareTo(kv2.Value.Connections)));
        if(rank)
        {
            var comp = Comparer<KeyValuePair<int, Node>>.Create((kv1, kv2) => kv1.Value.NumBigNeigbours.CompareTo(kv2.Value.NumBigNeigbours));
            var connections = maxNodeKv.Value.Connections;
            maxNodeKv = _nodes.Where(kv => kv.Value.Connections == connections).Min(comp);
        }

        CutNode(maxNodeKv);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        var numTestsw = int.Parse(Console.ReadLine());
        var results = new List<int>();

        for(var i=0; i<numTestsw; ++i)
        {
            var tree = new Tree(int.Parse(Console.ReadLine()));
            tree.ReadFromInput();

            tree.CutMax(true);
            tree.CutMax(false);

            results.Add(tree.Parts);
        }

        foreach(var n in results)
            Console.WriteLine(n);
    }
}