Problem: Maximal Network Rank

There is an infrastructure of `n` cities with some number of `roads`
connecting these cities. Each `roads[i] = [ai, bi]` indicates that there is a
bidirectional road between cities `ai` and `bi`.

The network rank of two different cities is defined as the total number of
directly connected roads to either city. If a road is directly connected to
both cities, it is only counted once.

The maximal network rank of the infrastructure is the maximum network rank of
all pairs of different cities.

Given the integer `n` and the array `roads`, return the maximal network rank
of the entire infrastructure.


Python solution:
import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def maximalNetworkRank(self, n: int, roads: List[List[int]]) -> int:
    degrees = [0] * n

    for u, v in roads:
      degrees[u] += 1
      degrees[v] += 1

    maxDegree1 = 0
    maxDegree2 = 0
    for degree in degrees:
      if degree > maxDegree1:
        maxDegree2 = maxDegree1
        maxDegree1 = degree
      elif degree > maxDegree2:
        maxDegree2 = degree

    countMaxDegree1 = 0
    countMaxDegree2 = 0
    for degree in degrees:
      if degree == maxDegree1:
        countMaxDegree1 += 1
      elif degree == maxDegree2:
        countMaxDegree2 += 1

    if countMaxDegree1 == 1:
      edgeCount = self._getEdgeCount(roads, degrees, maxDegree1, maxDegree2) + self._getEdgeCount(roads, degrees, maxDegree2, maxDegree1)
      return maxDegree1 + maxDegree2 - (countMaxDegree2 == edgeCount)
    else:
      edgeCount = self._getEdgeCount(roads, degrees, maxDegree1, maxDegree1)
      maxPossibleEdgeCount = countMaxDegree1 * (countMaxDegree1 - 1) // 2
      return 2 * maxDegree1 - (maxPossibleEdgeCount == edgeCount)

  def _getEdgeCount(self, roads: List[List[int]], degrees: List[int], degreeU: int, degreeV: int) -> int:
    edgeCount = 0
    for u, v in roads:
      if degrees[u] == degreeU and degrees[v] == degreeV:
        edgeCount += 1
    return edgeCount


Java solution:
class Solution {
  public int maximalNetworkRank(int n, int[][] roads) {
    int[] degrees = new int[n];

    for (int[] road : roads) {
      final int u = road[0];
      final int v = road[1];
      ++degrees[u];
      ++degrees[v];
    }

    // Find the first maximum and the second maximum degrees.
    int maxDegree1 = 0;
    int maxDegree2 = 0;
    for (final int degree : degrees)
      if (degree > maxDegree1) {
        maxDegree2 = maxDegree1;
        maxDegree1 = degree;
      } else if (degree > maxDegree2) {
        maxDegree2 = degree;
      }

    // There can be multiple nodes with `maxDegree1` or `maxDegree2`.
    // Find the counts of such nodes.
    int countMaxDegree1 = 0;
    int countMaxDegree2 = 0;
    for (final int degree : degrees)
      if (degree == maxDegree1)
        ++countMaxDegree1;
      else if (degree == maxDegree2)
        ++countMaxDegree2;

    if (countMaxDegree1 == 1) {
      // 1. If there is only one node with degree = `maxDegree1`, then we'll
      // need to use the node with degree = `maxDegree2`. The answer in general
      // will be (maxDegree1 + maxDegree2), but if the two nodes that we're
      // considering are connected, then we'll have to subtract 1.
      final int edgeCount = getEdgeCount(roads, degrees, maxDegree1, maxDegree2) +
                            getEdgeCount(roads, degrees, maxDegree2, maxDegree1);
      return maxDegree1 + maxDegree2 - (countMaxDegree2 == edgeCount ? 1 : 0);
    } else {
      // 2. If there are more than one node with degree = `maxDegree1`, then we
      // can consider `maxDegree1` twice, and we don't need to use `maxDegree2`.
      // The answer in general will be 2 * maxDegree1, but if the two nodes that
      // we're considering are connected, then we'll have to subtract 1.
      final int edgeCount = getEdgeCount(roads, degrees, maxDegree1, maxDegree1);
      final int maxPossibleEdgeCount = countMaxDegree1 * (countMaxDegree1 - 1) / 2;
      return 2 * maxDegree1 - (maxPossibleEdgeCount == edgeCount ? 1 : 0);
    }
  }

  // Returns the number of edges (u, v) where degress[u] == degreeU and
  // degrees[v] == degreeV.
  private int getEdgeCount(int[][] roads, int[] degrees, int degreeU, int degreeV) {
    int edgeCount = 0;
    for (int[] road : roads) {
      final int u = road[0];
      final int v = road[1];
      if (degrees[u] == degreeU && degrees[v] == degreeV)
        ++edgeCount;
    }
    return edgeCount;
  }
}


C++ solution:
class Solution {
 public:
  int maximalNetworkRank(int n, vector<vector<int>>& roads) {
    vector<int> degrees(n);

    for (const vector<int>& road : roads) {
      const int u = road[0];
      const int v = road[1];
      ++degrees[u];
      ++degrees[v];
    }

    // Find the first maximum and the second maximum degrees.
    int maxDegree1 = 0;
    int maxDegree2 = 0;
    for (const int degree : degrees) {
      if (degree > maxDegree1) {
        maxDegree2 = maxDegree1;
        maxDegree1 = degree;
      } else if (degree > maxDegree2) {
        maxDegree2 = degree;
      }
    }

    // There can be multiple nodes with `maxDegree1` or `maxDegree2`.
    // Find the counts of such nodes.
    int countMaxDegree1 = 0;
    int countMaxDegree2 = 0;
    for (const int degree : degrees)
      if (degree == maxDegree1)
        ++countMaxDegree1;
      else if (degree == maxDegree2)
        ++countMaxDegree2;

    if (countMaxDegree1 == 1) {
      // 1. If there is only one node with degree = `maxDegree1`, then we'll
      // need to use the node with degree = `maxDegree2`. The answer in general
      // will be (maxDegree1 + maxDegree2), but if the two nodes that we're
      // considering are connected, then we'll have to subtract 1.
      const int edgeCount =
          getEdgeCount(roads, degrees, maxDegree1, maxDegree2) +
          getEdgeCount(roads, degrees, maxDegree2, maxDegree1);
      return maxDegree1 + maxDegree2 - (countMaxDegree2 == edgeCount ? 1 : 0);
    } else {
      // 2. If there are more than one node with degree = `maxDegree1`, then we
      // can consider `maxDegree1` twice, and we don't need to use `maxDegree2`.
      // The answer in general will be 2 * maxDegree1, but if the two nodes that
      // we're considering are connected, then we'll have to subtract 1.
      const int edgeCount =
          getEdgeCount(roads, degrees, maxDegree1, maxDegree1);
      const int maxPossibleEdgeCount =
          countMaxDegree1 * (countMaxDegree1 - 1) / 2;
      return 2 * maxDegree1 - (maxPossibleEdgeCount == edgeCount ? 1 : 0);
    }
  }

 private:
  // Returns the number of edges (u, v) where degress[u] == degreeU and
  // degrees[v] == degreeV.
  int getEdgeCount(const vector<vector<int>>& roads, const vector<int>& degrees,
                   int degreeU, int degreeV) {
    int edgeCount = 0;
    for (const vector<int>& road : roads) {
      const int u = road[0];
      const int v = road[1];
      if (degrees[u] == degreeU && degrees[v] == degreeV)
        ++edgeCount;
    }
    return edgeCount;
  }
};