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.
Example 1:
Input: n = 4, roads = [[0,1],[0,3],[1,2],[1,3]] Output: 4 Explanation: The network rank of cities 0 and 1 is 4 as there are 4 roads that are connected to either 0 or 1. The road between 0 and 1 is only counted once.
Example 2:
Input: n = 5, roads = [[0,1],[0,3],[1,2],[1,3],[2,3],[2,4]] Output: 5 Explanation: There are 5 roads that are connected to cities 1 or 2.
Example 3:
Input: n = 8, roads = [[0,1],[1,2],[2,3],[2,4],[5,6],[5,7]] Output: 5 Explanation: The network rank of 2 and 5 is 5. Notice that all the cities do not have to be connected.
Constraints:
2 <= n <= 100
0 <= roads.length <= n * (n - 1) / 2
roads[i].length == 2
0 <= ai, bi <= n-1
ai != bi
- Each pair of cities has at most one road connecting them.
Related Topics:
Graph
// OJ: https://leetcode.com/problems/maximal-network-rank/
// Author: github.com/lzl124631x
// Time: O(N^2)
// Space: O(N^2)
class Solution {
public:
int maximalNetworkRank(int n, vector<vector<int>>& E) {
vector<unordered_set<int>> G(n);
for (auto &e : E) {
G[e[0]].insert(e[1]);
G[e[1]].insert(e[0]);
}
int ans = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
ans = max(ans, (int)(G[i].size() + G[j].size() - G[i].count(j)));
}
}
return ans;
}
};
Let deg[i]
be the degree of node i
. For node u
and v
, the answer is deg[u] + deg[v]
if they are not connected, and deg[u] + dev[v] - 1
otherwise.
Let first
be the greatest degree, second
be the second greatest degree (first
and second
can be the same if there are multiple nodes with the largest degree). We just need to consider the cities with first
and second
degrees because:
- The result of selecting from such nodes is at least
first + second - 1
(when they are connected). - If we select a city with degree
x < second
, then the result is at bestfirst + x < first + second
, i.e.first + x <= first + second - 1
, which is no better than selecting fromfirst
andsecond
So, selecting from first
and second
must be optimal.
Let x
be the number of cities with first
degree. So there are m
be the number of roads.
- If
x = 1
, then we must pick a city from the cities withsecond
degree. Enumerating such cities takesO(n)
time. - If
x > 1
and${x\choose 2} > m$ , then the roads don't cover all the possible connections between thosefirst
degree cities, so there must be a pair offirst
degree cities unconnected. Picking them results infirst * 2
. - IF
x > 1
and${x\choose 2} <= m$ , then we don't need to considersecond
degree city because its resultfirst + second
must be no better than the result of picking twofirst
degree cities,first + first - 1
. We just need to enumerate all the city pairs amongfirst
degree cities, which takesO(x * (x-1) / 2) = O(m)
time.
So overall this solution takes O(n + m)
time.
// OJ: https://leetcode.com/problems/maximal-network-rank/
// Author: github.com/lzl124631x
// Time: O(N + M)
// Space: O(N + M)
// Ref: https://leetcode-cn.com/problems/maximal-network-rank/solution/onm-mei-ju-fa-by-zerotrac2/
class Solution {
public:
int maximalNetworkRank(int n, vector<vector<int>>& A) {
if (A.empty()) return 0;
vector<unordered_set<int>> G(n);
vector<int> deg(n), firstNodes, secondNodes;
for (auto &e : A) {
int u = e[0], v = e[1];
G[u].insert(v);
G[v].insert(u);
deg[u]++;
deg[v]++;
}
int first = 0, second = 0, m = A.size();
for (int d : deg) {
if (d > first) {
second = first;
first = d;
} else if (d > second) second = d;
}
for (int i = 0; i < n; ++i) {
if (deg[i] == first) firstNodes.push_back(i);
else if (deg[i] == second) secondNodes.push_back(i);
}
if (firstNodes.size() == 1) {
int u = firstNodes[0];
for (int v : secondNodes) {
if (G[u].count(v) == 0) return first + second;
}
return first + second - 1;
} else {
if (firstNodes.size() * (firstNodes.size() - 1) / 2 > m) return first * 2;
for (int i = 0; i < firstNodes.size(); ++i) {
for (int j = i + 1; j < firstNodes.size(); ++j) {
if (G[firstNodes[i]].count(firstNodes[j]) == 0) return first * 2;
}
}
return first * 2 - 1;
}
}
};
// OJ: https://leetcode.com/problems/maximal-network-rank/
// Author: github.com/lzl124631x
// Time: O(N + M)
// Space: O(N)
// Ref: https://leetcode.com/problems/maximal-network-rank/discuss/889206/Java-2ms-O(m)
class Solution {
public:
int maximalNetworkRank(int n, vector<vector<int>>& E) {
vector<int> deg(n);
for (auto &e : E) {
deg[e[0]]++;
deg[e[1]]++;
}
int first = 0, second = 0, firstCnt = 0, secondCnt = 0, cnt = 0;
for (int i = 0; i < n; ++i) {
if (deg[i] > first) {
second = first;
first = deg[i];
} else if (deg[i] > second) second = deg[i];
}
for (int i = 0; i < n; ++i) {
firstCnt += deg[i] == first;
secondCnt += deg[i] == second;
}
if (firstCnt == 1) {
for (auto &e : E) {
int u = e[0], v = e[1];
cnt += (deg[u] == first && deg[v] == second) || (deg[u] == second && deg[v] == first);
}
return first + second - (secondCnt <= cnt); // cnt is the number of edges connecting the single `first`-tier node and all `second`-tier nodes. If `secondCnt <= cnt`, all `second`-tier nodes are connected with the `first`-tier node, and we need to subtract the answer by 1.
} else {
for (auto &e : E) {
int u = e[0], v = e[1];
cnt += deg[u] == first && deg[v] == first;
}
return first * 2 - ((firstCnt - 1) * firstCnt / 2 == cnt); // cnt is the number of edges connecting `first`-tier nodes. Only when all the `first`-tier nodes are interconnected ((firstCnt - 1) * firstCnt / 2 == cnt), we need to subtract the answer by 1
}
}
};