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

Previous submission (verdict: Wrong answer on test 2):
﻿new ProblemSolver().Solve();

class ProblemSolver
{
    private int n;
    private bool[] visited;
    private int[] inEdges, outEdges;
    private List<int>[] graph;

    public void Solve()
    {
        var testCases = Convert.ToInt32(Console.ReadLine().Trim());

        for (var i = 0; i < testCases; i++)
        {
            RunTestCase();
        }
    }

    void RunTestCase()
    {
        n = Convert.ToInt32(Console.ReadLine().Trim());

        graph = new List<int>[n];

        for (var i = 0; i < n; i++)
        {
            graph[i] = new List<int>();
        }

        for (var i = 0; i < n - 1; i++)
        {
            var row = Console.ReadLine()
                             .Trim()
                             .Split()
                             .Select(item => Convert.ToInt32(item))
                             .ToArray();

            var u = row[0] - 1;
            var v = row[1] - 1;

            graph[u].Add(v);
            graph[v].Add(u);
        }

        ExecuteRemoveOperation();
        ExecuteRemoveOperation();

        Console.WriteLine(CountConnectedComponents() - 2);
    }

    void ExecuteRemoveOperation()
    {
        inEdges = new int[n];
        outEdges = new int[n];
        visited = new bool[n];

        for (var i = 0; i < n; i++)
            if (!visited[i]) DFS(i);
       
        RemoveNodeWithMaxEdges();
    }

    void DFS(int node)
    {
        visited[node] = true;

        foreach (var child in graph[node])
        {
            if (!visited[child])
            {
                outEdges[node]++;
                inEdges[child]++;
                DFS(child);
            }
        }
    }

    void RemoveNodeWithMaxEdges()
    {
        var nodeToRemove = (-1, -1);

        for (int i = 0; i < n; i++)
        {
            if (inEdges[i] + outEdges[i] > nodeToRemove.Item1)
            {
                nodeToRemove = (inEdges[i] + outEdges[i], i);
            }
        }

        int node = nodeToRemove.Item2;

        graph[node] = new List<int>();

        for (int i = 0; i < n; i++)
        {
            graph[i].Remove(node);
        }
    }

    int CountConnectedComponents()
    {
        visited = new bool[n];
        
        var components = 0;

        for (int i = 0; i < n; i++)
        {
            if (visited[i])
            {
                continue;
            }

            components++;
            DFS(i);
        }

        return components;
    }
}


Submission (verdict: Accepted):
﻿new ProblemSolver().Solve();

class ProblemSolver
{
    private int n;
    private int[] level;
    private bool[] visited;
    private int[] inEdges, outEdges;
    private List<int>[] graph;

    public void Solve()
    {
        var testCases = Convert.ToInt32(Console.ReadLine().Trim());

        for (var i = 0; i < testCases; i++)
        {
            RunTestCase();
        }
    }

    void RunTestCase()
    {
        n = Convert.ToInt32(Console.ReadLine().Trim());

        graph = new List<int>[n];

        for (var i = 0; i < n; i++)
        {
            graph[i] = new List<int>();
        }

        for (var i = 0; i < n - 1; i++)
        {
            var row = Console.ReadLine()
                             .Trim()
                             .Split()
                             .Select(item => Convert.ToInt32(item))
                             .ToArray();

            var u = row[0] - 1;
            var v = row[1] - 1;

            graph[u].Add(v);
            graph[v].Add(u);
        }

        ExecuteRemoveOperation();
        ExecuteRemoveOperation();

        Console.WriteLine(CountConnectedComponents() - 2);
    }

    void ExecuteRemoveOperation()
    {
        level = new int[n];
        inEdges = new int[n];
        outEdges = new int[n];
        visited = new bool[n];

        for (var i = 0; i < n; i++)
            if (!visited[i]) DFS(i);
       
        RemoveNodeWithMaxEdges();
    }

    void DFS(int node)
    {
        visited[node] = true;

        foreach (var child in graph[node])
        {
            if (!visited[child])
            {
                outEdges[node]++;
                inEdges[child]++;
                level[child] = level[node] + 1;

                DFS(child);
            }
        }
    }

    void RemoveNodeWithMaxEdges()
    {
        var node = -1;
        var edges = -1;

        for (int i = 0; i < n; i++)
        {
            if (inEdges[i] + outEdges[i] > edges ||
                (node != -1 && inEdges[i] + outEdges[i] == edges && level[i] > level[node]))
            {
                node = i;
                edges = inEdges[i] + outEdges[i];
            }
        }

        graph[node] = new List<int>();

        for (int i = 0; i < n; i++)
        {
            graph[i].Remove(node);
        }
    }

    int CountConnectedComponents()
    {
        visited = new bool[n];
        
        var components = 0;

        for (int i = 0; i < n; i++)
        {
            if (visited[i])
            {
                continue;
            }

            components++;
            DFS(i);
        }

        return components;
    }
}