Given N cities number from 0 to N – 1. These are connected by M bidirectional roads. The ith road connects two distinct cities Edge[i][0] and Edge[i][1]. We are also given a string s, where s[i] will represent the colour associated with ith city. Each city will have 1 color only. Given Q queries, in the ith query, you are given 3 distinct colours query[i][0], query[i][1], and query[i][2]. For each query return “YES” if there exists a path such that only the city with these three colors comes in the way else return “NO“.
Examples:
Input: N = 6, M = 7, Q = 3, S = “abdebc” , Edge[][] = {{0, 1}, {0, 2}, {1, 3}, {1, 4}, {1, 2}, {2, 4}, {4,5}}, Query[] = {“abc”,”aec”,”azc”}
Output: YES NO NO
Explanation:
- Query 1: “abc” there exists a path 0 -> 1 -> 4 -> 5 which only consists of colours a, b and c.
- Query 2: “aec” There is no such path which will contain only a,e,c colours.
- Query 3: “azc” There is no such path which will contain only a,z,c colours.
Approach: This can be solved with the following idea:
Using Depth First Search technique, we can find path of colours possible from each edge. Store each path in dp. While answering the queries, we can find all possible combination formed from 3 colours. Check whether through dp it is possible or not.
Below are the steps to solve this problem:
- Create an adjacency list adj[] through edges.
- Initialize a dp[26][26][26], as there are 3 different colors.
-
Iterate in vertices and mark that node visited.
- For a node iterate through other nodes, which can be reached.
- Make a set of colors in the set and store the value in DP.
-
Iterate in queries:
-
For each colours set, make combinations and check whether it exist in dp
- If exist, Return Yes
- Otherwise, No
- Store the answers in ans vector.
-
For each colours set, make combinations and check whether it exist in dp
- Return ans.
Below is the implementation of the code:
// C++ code for the above approach: #include <bits/stdc++.h> #include <iostream> using namespace std;
// Function to iterate in array to // make color visited void dfs( int node, unordered_map< int , vector< int > >& adj,
string& col, set< char >& set, vector< bool >& vis)
{ // Make the node visited
vis[node] = 1;
for ( auto nbr : adj[node]) {
if (!vis[nbr] && col[nbr] == col[node]) {
dfs(nbr, adj, col, set, vis);
}
else {
// Insert in set
set.insert(col[nbr]);
}
}
} // Function to match path of string // according to roads vector<string> solve( int N, int M, int Q, string col,
vector<vector< int > >& Edge,
vector<string>& query)
{ vector< bool > vis(N, false );
// Intialise a dp as there are 3
// different colors
int dp[26][26][26] = { 0 };
// Create a adj list
unordered_map< int , vector< int > > adj;
for ( auto i : Edge) {
adj[i[0]].push_back(i[1]);
adj[i[1]].push_back(i[0]);
}
// Iterate for edges to make color
for ( int i = 0; i < N; i++) {
if (!vis[i]) {
set< char > set;
dfs(i, adj, col, set, vis);
for ( auto it1 : set) {
for ( auto it2 : set) {
// if(it1 != it2)
dp[it1 - 'a' ][col[i] - 'a' ][it2 - 'a' ]
= 1;
}
}
}
}
// Answering the queires
vector<string> ans;
for ( auto str : query) {
int a = str[0] - 'a' ;
int b = str[1] - 'a' ;
int c = str[2] - 'a' ;
// If path is matched
if (dp[a][b] || dp[a][b] || dp[b][a]
|| dp[b][a] || dp[a][b] || dp[b][a])
ans.push_back("YES");
// If path is not matched
else
ans.push_back("NO");
}
return ans;
} // Driver code int main()
{ int N = 6;
int M = 7;
int Q = 3;
string col = "abdebc";
vector<vector< int > > Edge
= { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 1, 4 },
{ 1, 2 }, { 2, 4 }, { 4, 5 } };
vector<string> query = { "abc", "aec", "azc" };
// Function call
vector<string> ans = solve(N, M, Q, col, Edge, query);
for ( auto a : ans) {
cout << a << " ";
}
return 0;
} |
import java.util.*;
public class Main {
// Function to iterate in array to make color visited
static void dfs( int node, HashMap<Integer, ArrayList<Integer>> adj,
String col, HashSet<Character> set, boolean [] vis) {
// Make the node visited
vis[node] = true ;
for ( int nbr : adj.get(node)) {
if (!vis[nbr] && col.charAt(nbr) == col.charAt(node)) {
dfs(nbr, adj, col, set, vis);
} else {
// Insert in set
set.add(col.charAt(nbr));
}
}
}
// Function to match path of string according to roads
static ArrayList<String> solve( int N, int M, int Q, String col,
int [][] Edge, String[] query) {
boolean [] vis = new boolean [N];
// Initialize a dp as there are 3 different colors
int [][][] dp = new int [ 26 ][ 26 ][ 26 ];
// Create an adj list
HashMap<Integer, ArrayList<Integer>> adj = new HashMap<>();
for ( int i = 0 ; i < N; i++) {
adj.put(i, new ArrayList<>());
}
// Iterate for edges to make color
for ( int [] i : Edge) {
adj.get(i[ 0 ]).add(i[ 1 ]);
adj.get(i[ 1 ]).add(i[ 0 ]);
}
// Iterate through edges to make color
for ( int i = 0 ; i < N; i++) {
if (!vis[i]) {
HashSet<Character> set = new HashSet<>();
dfs(i, adj, col, set, vis);
for ( char it1 : set) {
for ( char it2 : set) {
dp[it1 - 'a' ][col.charAt(i) - 'a' ][it2 - 'a' ] = 1 ;
}
}
}
}
// Answering the queries
ArrayList<String> ans = new ArrayList<>();
for (String str : query) {
int a = str.charAt( 0 ) - 'a' ;
int b = str.charAt( 1 ) - 'a' ;
int c = str.charAt( 2 ) - 'a' ;
// If path is matched
if (dp[a][b] == 1 || dp[a][b] == 1 || dp[b][a] == 1 ||
dp[b][a] == 1 || dp[a][b] == 1 || dp[b][a] == 1 ) {
ans.add( "YES" );
} else {
ans.add( "NO" );
}
}
return ans;
}
// Driver code
public static void main(String[] args) {
int N = 6 ;
int M = 7 ;
int Q = 3 ;
String col = "abdebc" ;
int [][] Edge = { { 0 , 1 }, { 0 , 2 }, { 1 , 3 }, { 1 , 4 }, { 1 , 2 }, { 2 , 4 }, { 4 , 5 } };
String[] query = { "abc" , "aec" , "azc" };
// Function call
ArrayList<String> ans = solve(N, M, Q, col, Edge, query);
for (String a : ans) {
System.out.print(a + " " );
}
}
} |
from collections import defaultdict
# Function to iterate in array to # make color visited def dfs(node, adj, col, color_set, vis):
# Make the node visited
vis[node] = 1
for nbr in adj[node]:
if not vis[nbr] and col[nbr] = = col[node]:
dfs(nbr, adj, col, color_set, vis)
else :
# Insert in set
color_set.add(col[nbr])
# Function to match path of string # according to roads def solve(N, M, Q, col, Edge, query):
vis = [ False ] * N
# Initialize a dp as there are 3
# different colors
dp = [[[ 0 ] * 26 for _ in range ( 26 )] for _ in range ( 26 )]
# Create an adjacency list
adj = defaultdict( list )
for i in Edge:
adj[i[ 0 ]].append(i[ 1 ])
adj[i[ 1 ]].append(i[ 0 ])
# Iterate for edges to make color
for i in range (N):
if not vis[i]:
color_set = set ()
dfs(i, adj, col, color_set, vis)
for it1 in color_set:
for it2 in color_set:
# if(it1 != it2)
dp[ ord (it1) - ord ( 'a' )][ ord (col[i]) - ord ( 'a' )][ ord (it2) - ord ( 'a' )] = 1
# Answering the queries
ans = []
for string in query:
a = ord (string[ 0 ]) - ord ( 'a' )
b = ord (string[ 1 ]) - ord ( 'a' )
c = ord (string[ 2 ]) - ord ( 'a' )
# If path is matched
if dp[a][b] or dp[a][b] or dp[b][a] or dp[b][a] or dp[a][b] or dp[b][a]:
ans.append( "YES" )
# If path is not matched
else :
ans.append( "NO" )
return ans
# Driver code if __name__ = = "__main__" :
N = 6
M = 7
Q = 3
col = "abdebc"
Edge = [[ 0 , 1 ], [ 0 , 2 ], [ 1 , 3 ], [ 1 , 4 ], [ 1 , 2 ], [ 2 , 4 ], [ 4 , 5 ]]
query = [ "abc" , "aec" , "azc" ]
# Function call
ans = solve(N, M, Q, col, Edge, query)
for a in ans:
print (a, end = " " )
|
// C# program for the above approach using System;
using System.Collections.Generic;
public class GFG {
// Function to iterate in array to
// make color visited
static void DFS( int node,
Dictionary< int , List< int > > adj,
ref string col, ref HashSet< char > set ,
ref List< bool > vis)
{
// Make the node visited
vis[node] = true ;
foreach ( var nbr in adj[node])
{
if (!vis[nbr] && col[nbr] == col[node]) {
DFS(nbr, adj, ref col, ref set , ref vis);
}
else {
// Insert in set
set .Add(col[nbr]);
}
}
}
// Function to match path of string
// according to roads
static List< string > Solve( int N, int M, int Q,
string col,
List<List< int > > Edge,
List< string > query)
{
List< bool > vis = new List< bool >( new bool [N]);
// Intialise a dp as there are 3
// different colors
int [, , ] dp = new int [26, 26, 26];
// Create an adj list
Dictionary< int , List< int > > adj
= new Dictionary< int , List< int > >();
foreach ( var i in Edge)
{
if (!adj.ContainsKey(i[0]))
adj[i[0]] = new List< int >();
if (!adj.ContainsKey(i[1]))
adj[i[1]] = new List< int >();
adj[i[0]].Add(i[1]);
adj[i[1]].Add(i[0]);
}
// Iterate for edges to make color
for ( int i = 0; i < N; i++) {
if (!vis[i]) {
HashSet< char > set = new HashSet< char >();
DFS(i, adj, ref col, ref set , ref vis);
foreach ( var it1 in set )
{
foreach ( var it2 in set )
{
// if(it1 != it2)
dp[it1 - 'a' , col[i] - 'a' ,
it2 - 'a' ]
= 1;
}
}
}
}
// Answering the queries
List< string > ans = new List< string >();
foreach ( var str in query)
{
int a = str[0] - 'a' ;
int b = str[1] - 'a' ;
int c = str[2] - 'a' ;
// If path is matched
if (dp[a, b, c] != 0 || dp[a, c, b] != 0
|| dp[b, a, c] != 0 || dp[b, c, a] != 0
|| dp != 0 || dp != 0)
ans.Add( "YES" );
// If path is not matched
else
ans.Add( "NO" );
}
return ans;
}
// Driver code
public static void Main()
{
int N = 6;
int M = 7;
int Q = 3;
string col = "abdebc" ;
List<List< int > > Edge = new List<List< int > >{
new List< int >{ 0, 1 }, new List< int >{ 0, 2 },
new List< int >{ 1, 3 }, new List< int >{ 1, 4 },
new List< int >{ 1, 2 }, new List< int >{ 2, 4 },
new List< int >{ 4, 5 }
};
List< string > query
= new List< string >{ "abc" , "aec" , "azc" };
// Function call
List< string > ans = Solve(N, M, Q, col, Edge, query);
foreach ( var a in ans) { Console.Write(a + " " ); }
}
} // This code is contributed by Susobhan Akhuli |
// Javascript program for the above approach // Function to iterate in array to // make color visited function DFS(node, adj, col, colorSet, vis) {
// Make the node visited
vis[node] = true ;
// Convert Map values to an array for iteration
const neighbors = Array.from(adj.get(node) || []);
for (const nbr of neighbors) {
if (!vis[nbr] && col[nbr] === col[node]) {
DFS(nbr, adj, col, colorSet, vis);
} else {
// Insert in set
colorSet.add(col[nbr]);
}
}
} // Function to match path of string // according to roads function Solve(N, M, Q, col, Edge, query) {
const vis = Array(N).fill( false );
// Intialise a dp as there are 3
// different colors
const dp = Array.from({ length: 26 }, () =>
Array.from({ length: 26 }, () => Array(26).fill(0))
);
// Create an adj list
const adj = new Map();
for (const i of Edge) {
if (!adj.has(i[0])) adj.set(i[0], []);
if (!adj.has(i[1])) adj.set(i[1], []);
adj.get(i[0]).push(i[1]);
adj.get(i[1]).push(i[0]);
}
// Iterate for edges to make color
for (let i = 0; i < N; i++) {
if (!vis[i]) {
const colorSet = new Set();
DFS(i, adj, col, colorSet, vis);
for (const it1 of colorSet) {
for (const it2 of colorSet) {
// if(it1 != it2)
dp[it1.charCodeAt() - 'a' .charCodeAt()][col[i].charCodeAt() - 'a' .charCodeAt()][it2.charCodeAt() - 'a' .charCodeAt()] = 1;
}
}
}
}
// Answering the queries
const ans = [];
for (const str of query) {
const a = str.charCodeAt(0) - 'a' .charCodeAt();
const b = str.charCodeAt(1) - 'a' .charCodeAt();
const c = str.charCodeAt(2) - 'a' .charCodeAt();
// If path is matched
if (dp[a][b] !== 0 || dp[a][b] !== 0 || dp[b][a] !== 0 || dp[b][a] !== 0 || dp[a][b] !== 0 || dp[b][a] !== 0) ans.push( "YES" );
// If path is not matched
else ans.push( "NO" );
}
return ans;
} // Driver code const N = 6; const M = 7; const Q = 3; const col = "abdebc" ;
const Edge = [ [0, 1], [0, 2], [1, 3],
[1, 4], [1, 2], [2, 4],
[4, 5]
]; const query = [ "abc" , "aec" , "azc" ];
// Function call const ans = Solve(N, M, Q, col, Edge, query); console.log(ans.join( " " ));
// This code is contributed by Susobhan Akhuli |
YES NO NO
Time Complexity: O(N * M + Q)
Auxiliary Space: O(N)