forked from 7oSkaaa/LeetCode_DailyChallenge_2023
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '7oSkaaa:main' into main
- Loading branch information
Showing
3 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
100 changes: 100 additions & 0 deletions
100
...le/30- Remove Max Number of Edges to Keep Graph Fully Traversable (Mahmoud Aboelsoud).cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// Author: Mahmoud Aboelsoud | ||
|
||
class Solution { | ||
public: | ||
// we need to find the number of edges that we can remove to make the graph fully traversable | ||
// which mean we need the minimum number of edges to connect to make the graph fully traversable by Alice and Bob | ||
// we can use DSU to solve this problem | ||
// we can make two graphs one for Alice and one for Bob | ||
// we need to find the minimum number of edges used in both graphs to make each graph connected | ||
// then we can remove the edges that are not used in both graphs | ||
// we can use the third type of edges to connect the nodes in both graphs | ||
// then we can check the needed number of edges to make both graphs connected from the other two types of edges | ||
|
||
|
||
// DSU implementation | ||
struct DSU{ | ||
|
||
vector<int> parent, set_size; | ||
|
||
DSU(int n){ | ||
parent.assign(n + 1, 0); | ||
set_size.assign(n + 1, 1); | ||
|
||
for(int i = 1; i <= n; i++) | ||
parent[i] = i; | ||
} | ||
|
||
int find_set(int v){ | ||
if(v == parent[v]) return v; | ||
|
||
return parent[v] = find_set(parent[v]); | ||
} | ||
|
||
void union_sets(int a, int b){ | ||
a = find_set(a); | ||
b = find_set(b); | ||
if(a != b){ | ||
if(set_size[a] < set_size[b]) | ||
swap(a, b); | ||
parent[b] = a; | ||
set_size[a] += set_size[b]; | ||
} | ||
} | ||
|
||
bool same_set(int a, int b){ | ||
a = find_set(a); | ||
b = find_set(b); | ||
|
||
return a == b; | ||
} | ||
}; | ||
|
||
|
||
int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) { | ||
// we make 2 DSU one for Alice and one for Bob | ||
DSU dsu1(n), dsu2(n); | ||
|
||
// cnt: number of edges that is required to make each of the 2 graphs connected | ||
int cnt = 0; | ||
|
||
// we can use the third type of edges to connect the nodes in both graphs | ||
for(auto&i: edges){ | ||
// if the edge is of type 3 and the nodes are not connected in both graphs | ||
if(i[0] == 3 && !dsu1.same_set(i[1], i[2])){ | ||
// we can use this edge to connect the nodes in both graphs | ||
// we increase the number of required edges by 1 | ||
cnt++; | ||
// we connect the nodes in both graphs | ||
dsu1.union_sets(i[1], i[2]); | ||
dsu2.union_sets(i[1], i[2]); | ||
} | ||
} | ||
|
||
// we check the needed number of edges to make both graphs connected from the other two types of edges | ||
for(auto&i: edges){ | ||
// if the edge is of type 1 and the nodes are not connected in Alice's graph | ||
if(i[0] == 1 && !dsu1.same_set(i[1], i[2])){ | ||
// we can use this edge to connect the nodes in Alice's graph | ||
dsu1.union_sets(i[1], i[2]); | ||
// we increase the number of required edges by 1 | ||
cnt++; | ||
} | ||
// if the edge is of type 2 and the nodes are not connected in Bob's graph | ||
else if(i[0] == 2 && !dsu2.same_set(i[1], i[2])){ | ||
// we can use this edge to connect the nodes in Bob's graph | ||
dsu2.union_sets(i[1], i[2]); | ||
// we increase the number of required edges by 1 | ||
cnt++; | ||
} | ||
} | ||
|
||
// then we check if all nodes in the given graph are connected in both graphs | ||
// we do that by checking if the number of nodes in the set of the first node is equal to the number of nodes in the graph | ||
// if not then we return -1 | ||
if(dsu1.set_size[dsu1.find_set(1)] != n || dsu2.set_size[dsu2.find_set(1)] != n) return -1; | ||
|
||
// else we return the number of edges that we can remove to make the graph fully traversable | ||
return edges.size() - cnt; | ||
} | ||
}; |
54 changes: 54 additions & 0 deletions
54
...aversable/30- Remove Max Number of Edges to Keep Graph Fully Traversable (Mina Magdy).cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Author: Mina Magdy | ||
|
||
// create a structure for disjoint set union data structure | ||
struct DSU { | ||
int cc; // number of connected components | ||
vector<int> p, s; // vector for storing parent and size of connected components | ||
DSU(int n) { // constructor | ||
cc = n; // initially number of connected components are equal to the number of vertices | ||
p.resize(n + 1); // resize vector to hold parent of each vertex | ||
iota(p.begin(), p.end(), 0); // initialize the parent vector with indices | ||
s.assign(n + 1, 1); // initially all connected components have size 1 | ||
} | ||
int find(int x) { // function to find the parent of a vertex and do path compression | ||
return (x == p[x] ? x : p[x] = find(p[x])); | ||
} | ||
bool same_group(int u, int v) { // function to check if two vertices are in the same group or not | ||
return find(u) == find(v); | ||
} | ||
void join(int u, int v) { // function to join two vertices into a single group | ||
int r1 = find(u), r2 = find(v); | ||
if (r1 == r2) // already in the same group | ||
return; | ||
if (s[r1] < s[r2]) // make smaller group as child of the larger group | ||
swap(r1, r2); | ||
p[r2] = r1; // make parent of r2 as r1 | ||
s[r1] += s[r2]; // add size of r2 to size of r1 | ||
cc--; // decrease the number of connected components | ||
} | ||
}; | ||
|
||
int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) { | ||
sort(edges.begin(), edges.end(), greater<>()); // sort the edges in descending order of type | ||
DSU dsu1(n), dsu2(n); // create two instances of disjoint set union data structure | ||
int cnt = 0; // count of number of edges added to graph | ||
for (auto& v : edges) { // iterate through all edges | ||
int t = 0; // type of edge added to graph | ||
if (v[0] & 1) { // check if edge is of type 1 or 3 | ||
if (dsu1.same_group(v[1], v[2])) // if vertices are already in the same group, skip | ||
continue; | ||
dsu1.join(v[1], v[2]); // join the vertices and decrease number of connected components | ||
t |= 1; // set the type of edge | ||
} | ||
if (v[0] & 2) { // check if edge is of type 2 or 3 | ||
if (dsu2.same_group(v[1], v[2])) // if vertices are already in the same group, skip | ||
continue; | ||
dsu2.join(v[1], v[2]); // join the vertices and decrease number of connected components | ||
t |= 2; // set the type of edge | ||
} | ||
cnt += t > 0; // if an edge is added to the graph, increase the count | ||
} | ||
if (dsu1.cc != 1 || dsu2.cc != 1) // if the graph is not connected, return -1 | ||
return -1; | ||
return edges.size() - cnt; // return the number of edges removed from the graph | ||
} |
70 changes: 70 additions & 0 deletions
70
...aversable/30- Remove Max Number of Edges to Keep Graph Fully Traversable (Omar_Sanad).cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// author : Omar Sanad | ||
|
||
// DSU Structure | ||
template < typename T = int > struct DSU { | ||
vector < T > par, gr_sz; | ||
T groups; | ||
|
||
// DSU constructor | ||
DSU(int numNodes) { | ||
groups = numNodes; | ||
gr_sz.assign(numNodes + 1, 1), par.resize(numNodes + 1); | ||
for(int i = 1; i <= numNodes; i++) par[i] = i; | ||
} | ||
|
||
// operator = , to assign one dsu to another | ||
DSU operator = (DSU& other) { | ||
par = other.par; | ||
gr_sz = other.gr_sz; | ||
groups = other.groups; | ||
return *this; | ||
} | ||
|
||
T getRoot(int node) {return par[node] = (par[node] == node ? node : getRoot(par[node]));} | ||
T get_size(int node) {return gr_sz[getRoot(node)];} | ||
bool SameGr(int u, int v){return getRoot(u) == getRoot(v);} | ||
|
||
void combine(int a, int b) { | ||
int root_of_a = getRoot(a), root_of_b = getRoot(b); | ||
if(root_of_a == root_of_b) return; // They are already in the same group | ||
if(gr_sz[root_of_a] < gr_sz[root_of_b]) swap(root_of_a, root_of_b); | ||
gr_sz[root_of_a] += gr_sz[root_of_b], par[root_of_b] = root_of_a; | ||
groups--; | ||
} | ||
}; | ||
|
||
class Solution { | ||
public: | ||
int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) { | ||
|
||
// Declare the dsu that has the paths that both Alice and Bob can use | ||
DSU du(n); | ||
|
||
// The number of used edges | ||
int ans = 0; | ||
|
||
// use all edges of type 3 (both Alice and Bob can use), (the ones you need only) | ||
for (auto &e : edges) | ||
if (e.front() == 3 and not du.SameGr(e[1], e[2])) | ||
ans++, du.combine(e[1], e[2]); | ||
|
||
|
||
// Declare another two DSUs, one for Alice and the other one for Bob. | ||
DSU Alice = du, Bob = du; | ||
|
||
// use the edges you need in the other two types | ||
for (auto &e : edges) | ||
if (e[0] == 1) { // Alice | ||
if (not Alice.SameGr(e[1], e[2])) | ||
ans++, Alice.combine(e[1], e[2]); | ||
} | ||
else if (e[0] == 2) { // Bob | ||
if (not Bob.SameGr(e[1], e[2])) | ||
ans++, Bob.combine(e[1], e[2]); | ||
} | ||
|
||
// if Both Alice and Bob can fully traverse the graph | ||
// return the number of deleted edges. | ||
return Alice.groups == 1 and Bob.groups == 1 ? edges.size() - ans : -1; | ||
} | ||
}; |