New Problem Solution - "1857. Largest Color Value in a Directed Graph"

This commit is contained in:
Hao Chen 2021-05-10 15:30:54 +08:00
parent 2525f8a431
commit 98946691a2
2 changed files with 188 additions and 1 deletions

View File

@ -9,6 +9,7 @@ LeetCode
| # | Title | Solution | Difficulty |
|---| ----- | -------- | ---------- |
|1857|[Largest Color Value in a Directed Graph](https://leetcode.com/problems/largest-color-value-in-a-directed-graph/) | [C++](./algorithms/cpp/largestColorValueInADirectedGraph/LargestColorValueInADirectedGraph.cpp)|Hard|
|1856|[Maximum Subarray Min-Product](https://leetcode.com/problems/maximum-subarray-min-product/) | [C++](./algorithms/cpp/maximumSubarrayMinProduct/MaximumSubarrayMinProduct.cpp)|Medium|
|1855|[Maximum Distance Between a Pair of Values](https://leetcode.com/problems/maximum-distance-between-a-pair-of-values/) | [C++](./algorithms/cpp/maximumDistanceBetweenAPairOfValues/MaximumDistanceBetweenAPairOfValues.cpp)|Medium|
|1854|[Maximum Population Year](https://leetcode.com/problems/maximum-population-year/) | [C++](./algorithms/cpp/maximumPopulationYear/MaximumPopulationYear.cpp)|Easy|
@ -543,7 +544,7 @@ LeetCode
|2|[Add Two Numbers](https://leetcode.com/problems/add-two-numbers/)| [C++](./algorithms/cpp/addTwoNumbers/addTwoNumbers.cpp)|Medium|
|1|[Two Sum](https://leetcode.com/problems/two-sum/)| [C++](./algorithms/cpp/twoSum/twoSum.cpp), [Go](./algorithms/golang/twoSum/twoSum.go)|Easy|
l
### LeetCode Shell
@ -562,3 +563,4 @@ LeetCode
|2|[Search Range in Binary Search Tree](http://www.lintcode.com/en/problem/search-range-in-binary-search-tree/) | [Java](./algorithms/java/src/searchRangeInBinarySearchTree/searchRangeInBinarySearchTree.java)|Medium|

View File

@ -0,0 +1,185 @@
// Source : https://leetcode.com/problems/largest-color-value-in-a-directed-graph/
// Author : Hao Chen
// Date : 2021-05-10
/*****************************************************************************************************
*
* There is a directed graph of n colored nodes and m edges. The nodes are numbered from 0 to n - 1.
*
* You are given a string colors where colors[i] is a lowercase English letter representing the color
* of the i^th node in this graph (0-indexed). You are also given a 2D array edges where edges[j] =
* [aj, bj] indicates that there is a directed edge from node aj to node bj.
*
* A valid path in the graph is a sequence of nodes x1 -> x2 -> x3 -> ... -> xk such that there is a
* directed edge from xi to xi+1 for every 1 <= i < k. The color value of the path is the number of
* nodes that are colored the most frequently occurring color along that path.
*
* Return the largest color value of any valid path in the given graph, or -1 if the graph contains a
* cycle.
*
* Example 1:
*
* Input: colors = "abaca", edges = [[0,1],[0,2],[2,3],[3,4]]
* Output: 3
* Explanation: The path 0 -> 2 -> 3 -> 4 contains 3 nodes that are colored "a" (red in the above
* image).
*
* Example 2:
*
* Input: colors = "a", edges = [[0,0]]
* Output: -1
* Explanation: There is a cycle from 0 to 0.
*
* Constraints:
*
* n == colors.length
* m == edges.length
* 1 <= n <= 10^5
* 0 <= m <= 10^5
* colors consists of lowercase English letters.
* 0 <= aj, bj < n
******************************************************************************************************/
const int COLOR_CNT = 26;
class Node {
public:
Node(char c) {
incomming = 0;
color = c;
processed = false;
memset(colors, 0, sizeof(colors));
}
void AddMyColor() { colors[color]++; }
void Processed() { processed = true; }
bool isProcessed() { return processed; }
void AddIncomming(int n=1) { incomming += n;}
int Incomming() {return incomming;}
void AddChildNode(int n) { children.push_back(n); }
vector<int>& Children() { return children; }
int ChildrenCount() { return children.size(); }
int* Colors() {return colors;}
int MaxColorValue() {
int m = -1;
for(auto c: colors) {
m = max(m, c);
}
return m;
}
void MergeChildColors(Node& child){
int* c = child.Colors();
for(int i=0; i<COLOR_CNT; i++) {
colors[i] = max(colors[i], c[i]);
}
}
private:
int incomming; // incomming connection
char color; // node's color
bool processed; // if the node has been processed
int colors[COLOR_CNT]; // the colors count stastices
vector<int> children; // children nodes
};
class Solution {
private:
void print(vector<int>& v) {
cout << "[";
int i = 0;
for(; i<v.size()-1; i++) {
cout << v[i] << ",";
}
cout << v[i] << "]" << endl;
}
private:
int nodes_cnt;
vector<Node> nodes;
public:
int largestPathValue(string colors, vector<vector<int>>& edges) {
nodes_cnt = colors.size() ;
for(int i=0; i<nodes_cnt; i++) {
Node n( colors[i]-'a');
nodes.push_back(n);
}
for(auto& e : edges) {
nodes[e[0]].AddChildNode(e[1]);
nodes[e[1]].AddIncomming();
}
vector<bool> visited(nodes_cnt, false);
// We can do toplogical sort
//
//vector<int> topSort;
//for(int id=0; id <nodes_cnt; id++){
// auto& n = nodes[id];
// topologicalSort(id, topSort, visited);
//}
//print(topSort);
int m = -1;
for (int i=0; i<nodes_cnt; i++) {
//int id = topSort[i];
int id = i;
auto& n = nodes[id];
//using to check cycle.
std::fill(visited.begin(), visited.end(), false);
bool succ = travel(id, visited);
if (!succ) return -1;
m = max(m, nodes[id].MaxColorValue());
}
return m;
}
void topologicalSort(int i, vector<int>& topSort, vector<bool>& visited) {
if (visited[i]) return;
visited[i] = true;
for(auto& id : nodes[i].Children()) {
if (!visited[id]) {
topologicalSort(id, topSort, visited);
}
}
topSort.push_back(i);
}
//return true if it is successful
//return false if there is an error - has cycle
bool travel(int i, vector<bool>& visited ) {
//this node has been processed already
if (nodes[i].isProcessed()) return true;
//cycled
if (visited[i]) return false;
visited[i] = true;
// leaf node
if (nodes[i].ChildrenCount() <= 0 ) {
nodes[i].AddMyColor();
nodes[i].Processed();
return true;
}
for(auto& n : nodes[i].Children() ) {
bool succ = travel(n, visited);
if (!succ) return false;
nodes[i].MergeChildColors( nodes[n] );
}
nodes[i].AddMyColor();
nodes[i].Processed();
//cout << "["<< i << "]: " ;
//for(int k=0; k<26; k++) {
// cout << nodes[i].colors[k] << " ";
//}
//cout << endl;
return true;
}
};