图好题选编 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 boolean [] visited;boolean [] onPath;void traverse (Graph graph, int s) { if (visited[s]) return ; visited[s] = true ; onPath[s] = true ; for (int neighbor : graph.neighbors(s)) { traverse(graph, neighbor); } onPath[s] = false ; }
directed acyclic graph (DAG )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class LeetCode797 { List<List<Integer>> res; public List<List<Integer>> allPathsSourceTarget (int [][] graph) { res=new ArrayList <>(); dfs(graph,0 ,new LinkedList <>()); return res; } void dfs (int [][] graph, int start, LinkedList<Integer> path) { path.add(start); int n= graph.length; if (start==n-1 ){ res.add(new ArrayList <>(path)); path.removeLast(); return ; } for (int i : graph[start]) { dfs(graph,i,path); } path.removeLast(); } }
环检测算法
看到依赖问题,首先想到的就是把问题转化成「有向图」这种数据结构,只要图中存在环,那就说明存在循环依赖 。
只要会遍历,就可以判断图中是否存在环了
法一:DFS 借助 onPath 数组判断是否存在环
遍历所有节点;若某一路径上出现重复节点,则存在环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class LeetCode207 { List<Integer>[] graph; boolean isCycle; boolean [] visited; boolean [] onPath; public boolean canFinish (int numCourses, int [][] prerequisites) { graph=buildGraph(numCourses,prerequisites); visited=new boolean [graph.length]; onPath=new boolean [graph.length]; for (int i = 0 ; i < graph.length; i++) { dfs(i); } return !isCycle; } List<Integer>[] buildGraph(int num, int [][] pres){ List<Integer>[] graph=new List [num]; for (int i = 0 ; i < graph.length; i++) { graph[i]=new LinkedList <>(); } for (int [] pre : pres) { int from=pre[1 ]; int to=pre[0 ]; graph[from].add(to); } return graph; } void dfs (int start) { if (onPath[start]){ isCycle=true ; } if (visited[start] || isCycle){ return ; } visited[start]=true ; onPath[start]=true ; for (Integer i : graph[start]) { dfs(i); } onPath[start]=false ; } }
法二:BFS 借助 indegree
数组记录每个节点的「入度」
若某节点没有入度,则可以作为topological sort的起点,加入队列进行遍历
如果所有节点都被遍历,则不成环,否则成环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public boolean canFinish (int numCourses, int [][] prerequisites) { List<Integer>[] graph=new List [numCourses]; for (int i = 0 ; i < graph.length; i++) { graph[i]=new LinkedList <>(); } int [] inDegree=new int [graph.length]; for (int [] pre : prerequisites) { int to=pre[0 ]; int from=pre[1 ]; graph[from].add(to); inDegree[to]++; } int count=0 ; Deque<Integer> queue=new LinkedList <>(); for (int i = 0 ; i < inDegree.length; i++) { if (inDegree[i]==0 ){ queue.offer(i); } } while (!queue.isEmpty()){ int pre=queue.poll(); count++; for (int next : graph[pre]) { inDegree[next]--; if (inDegree[next]==0 ){ queue.offer(next); } } } return count==numCourses ? true : false ; }
拓扑排序:
Topological Sorting
直观地说就是,让你把一幅图「拉平」,而且这个「拉平」的图里面,所有箭头方向都是一致的
如果一幅图是「有向无环图」,那么一定可以进行拓扑排序。
将后序遍历的结果进行反转,就是拓扑排序的结果 。
法一:DFS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 public class LeetCode210 { List<Integer>[] graph; boolean [] visited; boolean [] onPath; boolean hasCycle; LinkedList<Integer> path; public int [] findOrder(int numCourses, int [][] prerequisites) { graph=build(numCourses,prerequisites); path=new LinkedList <>(); visited=new boolean [numCourses]; onPath=new boolean [numCourses]; for (int i = 0 ; i < numCourses; i++) { dfs(i); } if (hasCycle){ return new int [0 ]; }else { Collections.reverse(path); int [] res=new int [path.size()]; for (int i = 0 ; i < res.length; i++) { res[i]=path.get(i); } return res; } } List<Integer>[] build(int num, int [][] pres){ LinkedList<Integer>[] graph=new LinkedList [num]; for (int i = 0 ; i < num; i++) { graph[i]=new LinkedList <>(); } for (int [] pre : pres) { int from=pre[1 ]; int to=pre[0 ]; graph[from].add(to); } return graph; } void dfs (int start) { if (onPath[start]){ hasCycle=true ; } if (hasCycle || visited[start]){ return ; } visited[start]=true ; onPath[start]=true ; for (int i : graph[start]) { dfs(i); } path.add(start); onPath[start]=false ; } }
法二:BFS 同207的BFS算法,入度为0队列弹出节点的顺序即为拓扑排序结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public int [] findOrder(int numCourses, int [][] prerequisites) { List<Integer>[] graph=new List [numCourses]; int [] inDegree=new int [numCourses]; for (int i = 0 ; i < graph.length; i++) { graph[i]=new LinkedList <>(); } for (int [] pre : prerequisites) { int to=pre[0 ]; int from=pre[1 ]; graph[from].add(to); inDegree[to]++; } int count=0 ; int [] res=new int [numCourses]; Deque<Integer> queue=new LinkedList <>(); for (int i = 0 ; i < inDegree.length; i++) { if (inDegree[i]==0 ){ queue.offer(i); } } while (!queue.isEmpty()){ int pre=queue.poll(); res[count++]=pre; for (Integer next : graph[pre]) { inDegree[next]--; if (inDegree[next]==0 ){ queue.offer(next); } } } if (count<numCourses){ return new int []{}; }else { return res; } }
Dijkstra
1 2 int [] dijkstra(int start, List<Integer>[] graph);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 int weight (int from, int to) ;List<Integer> adj (int s) ; int [] dijkstra(int start, List<Integer>[] graph) { int V = graph.length; int [] distTo = new int [V]; Arrays.fill(distTo, Integer.MAX_VALUE); distTo[start] = 0 ; Queue<State> pq = new PriorityQueue <>((a, b) -> { return a.distFromStart - b.distFromStart; }); pq.offer(new State (start, 0 )); while (!pq.isEmpty()) { State curState = pq.poll(); int curNodeID = curState.id; int curDistFromStart = curState.distFromStart; if (curNodeID == end) { return curDistFromStart; } if (curDistFromStart > distTo[curNodeID]) { continue ; } for (int nextNodeID : adj(curNodeID)) { int distToNextNode = distTo[curNodeID] + weight(curNodeID, nextNodeID); if (distTo[nextNodeID] > distToNextNode) { distTo[nextNodeID] = distToNextNode; pq.offer(new State (nextNodeID, distToNextNode)); } } } return distTo; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 class State { int id; int dist; State(int id, int dist){ this .id=id; this .dist=dist; } } public int networkDelayTime (int [][] times, int n, int k) { List<int []>[] graph=new List [n+1 ]; for (int i = 1 ; i <= n; i++) { graph[i]=new LinkedList <>(); } for (int [] time : times) { int from=time[0 ]; int to=time[1 ]; int edge=time[2 ]; graph[from].add(new int []{to,edge}); } int [] md=new int [n+1 ]; Arrays.fill(md,Integer.MAX_VALUE); md[k]=0 ; PriorityQueue<State> pq=new PriorityQueue <>(new Comparator <State>() { @Override public int compare (State o1, State o2) { return o1.dist-o2.dist; } }); pq.offer(new State (k,0 )); while (!pq.isEmpty()){ State cur=pq.poll(); if (md[cur.id]<cur.dist){ continue ; } for (int [] next : graph[cur.id]) { int to=next[0 ]; int edge=next[1 ]; if (cur.dist+edge<md[to]){ md[to]=cur.dist+edge; pq.offer(new State (to,md[to])); } } } int max=Integer.MIN_VALUE; for (int i = 1 ; i <= n; i++) { max=Math.max(max,md[i]); } return max==Integer.MAX_VALUE ? -1 : max; }
相比最正统的dijkstra,注意:
只求到某一点的最短距离,可以提前return
考虑经过的节点数的限制,若不满足则continue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 public int findCheapestPrice (int n, int [][] flights, int src, int dst, int K) { List<int []>[] graph = new LinkedList [n]; for (int i = 0 ; i < n; i++) { graph[i] = new LinkedList <>(); } for (int [] edge : flights) { int from = edge[0 ]; int to = edge[1 ]; int price = edge[2 ]; graph[from].add(new int []{to, price}); } K++; return dijkstra(graph, src, K, dst); } class State { int id; int costFromSrc; int nodeNumFromSrc; State(int id, int costFromSrc, int nodeNumFromSrc) { this .id = id; this .costFromSrc = costFromSrc; this .nodeNumFromSrc = nodeNumFromSrc; } } int dijkstra (List<int []>[] graph, int src, int k, int dst) { int [] distTo = new int [graph.length]; int [] nodeNumTo = new int [graph.length]; Arrays.fill(distTo, Integer.MAX_VALUE); Arrays.fill(nodeNumTo, Integer.MAX_VALUE); distTo[src] = 0 ; nodeNumTo[src] = 0 ; Queue<State> pq = new PriorityQueue <>((a, b) -> { return a.costFromSrc - b.costFromSrc; }); pq.offer(new State (src, 0 , 0 )); while (!pq.isEmpty()) { State curState = pq.poll(); int curNodeID = curState.id; int costFromSrc = curState.costFromSrc; int curNodeNumFromSrc = curState.nodeNumFromSrc; if (curNodeID == dst) { return costFromSrc; } if (curNodeNumFromSrc == k) { continue ; } for (int [] neighbor : graph[curNodeID]) { int nextNodeID = neighbor[0 ]; int costToNextNode = costFromSrc + neighbor[1 ]; int nextNodeNumFromSrc = curNodeNumFromSrc + 1 ; if (distTo[nextNodeID] > costToNextNode) { distTo[nextNodeID] = costToNextNode; nodeNumTo[nextNodeID] = nextNodeNumFromSrc; } if (costToNextNode > distTo[nextNodeID] && nextNodeNumFromSrc > nodeNumTo[nextNodeID]) { continue ; } pq.offer(new State (nextNodeID, costToNextNode, nextNodeNumFromSrc)); } } return -1 ; }
名人节点的出度为 0
,入度为 n - 1
。
图有两种存储形式,一种是邻接表,一种是邻接矩阵,邻接表的主要优势是节约存储空间 ;邻接矩阵的主要优势是可以迅速判断两个节点是否相邻 。
虽然判断一个人「是名人」必须用一个 for 循环,但判断一个人「不是名人」就不用这么麻烦了。
因为「名人」的定义保证了「名人」的唯一性,所以我们可以利用排除法,先排除那些显然不是「名人」的人,从而避免 for 循环的嵌套,降低时间复杂度 。
我们可以不断从候选人中选两个出来,然后排除掉一个,直到最后只剩下一个候选人,这时候再使用一个 for 循环判断这个候选人是否是货真价实的「名人」 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public int findCelebrity (int n) { int candidate=0 ; for (int other = 0 ; other < n; other++) { if (knows(candidate,other) || !knows(other,candidate)){ candidate=other; } } for (int other = 0 ; other < n; other++) { if (other==candidate){ continue ; } if (knows(candidate,other) || !knows(other,candidate)){ return -1 ; } } return candidate; }
依葫芦画瓢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class LeetCode997 { public int findJudge (int n, int [][] trust) { boolean [][] matrix=new boolean [n+1 ][n+1 ]; for (int [] arr : trust) { int a=arr[0 ]; int b=arr[1 ]; matrix[a][b]=true ; } int candidate=1 ; for (int other = 2 ; other <= n; other++) { if (!matrix[other][candidate] || matrix[candidate][other]){ candidate=other; } } for (int i = 1 ; i <= n; i++) { if (i!=candidate && !matrix[i][candidate] || matrix[candidate][i]){ return -1 ; } } return candidate; } }
818. Race Car https://leetcode.com/problems/race-car/discuss/124326/Summary-of-the-BFS-and-DP-solutions-with-intuitive-explanation
BFS: slow! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public int racecar (int target) { Set<String> set=new HashSet <>(); PriorityQueue<int []> pq=new PriorityQueue <>((a,b)->(a[2 ]-b[2 ])); pq.offer(new int []{0 ,1 ,0 }); while (!pq.isEmpty()){ int [] cur=pq.poll(); int curId=cur[0 ]; int curSpeed=cur[1 ]; int curStep=cur[2 ]; if (curId==target){ return curStep; } int nextStep=curStep+1 ; int nextId=curId+curSpeed; int nextSpeed=curSpeed*2 ; String s=nextId+"," +nextSpeed; if (nextId>=0 && nextSpeed<=2 *target &&!set.contains(s)){ set.add(s); pq.offer(new int []{nextId,nextSpeed,nextStep}); } nextSpeed=curSpeed>0 ? -1 : 1 ; nextId=curId; s=nextId+"," +nextSpeed; if (!set.contains(s)){ set.add(s); pq.offer(new int []{nextId,nextSpeed,nextStep}); } } return -1 ; }
Dijkstra 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class Solution { public int racecar (int target) { int K = 33 - Integer.numberOfLeadingZeros(target - 1 ); int barrier = 1 << K; int [] dist = new int [2 * barrier + 1 ]; Arrays.fill(dist, Integer.MAX_VALUE); dist[target] = 0 ; PriorityQueue<Node> pq = new PriorityQueue <Node>( (a, b) -> a.steps - b.steps); pq.offer(new Node (0 , target)); while (!pq.isEmpty()) { Node node = pq.poll(); int steps = node.steps, targ1 = node.target; if (dist[Math.floorMod(targ1, dist.length)] > steps) continue ; for (int k = 0 ; k <= K; ++k) { int walk = (1 << k) - 1 ; int targ2 = walk - targ1; int steps2 = steps + k + (targ2 != 0 ? 1 : 0 ); if (Math.abs(targ2) <= barrier && steps2 < dist[Math.floorMod(targ2, dist.length)]) { pq.offer(new Node (steps2, targ2)); dist[Math.floorMod(targ2, dist.length)] = steps2; } } } return dist[0 ]; } } class Node { int steps, target; Node(int s, int t) { steps = s; target = t; } }
1136. Parallel Courses 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public int minimumSemesters (int n, int [][] relations) { int [] ins=new int [n+1 ]; List<Integer>[] graph=new List [n+1 ]; for (int i = 1 ; i <= n; i++) { graph[i]=new ArrayList <>(); } for (int [] relation : relations) { int from=relation[0 ]; int to=relation[1 ]; graph[from].add(to); ins[to]++; } Deque<Integer> q=new LinkedList <>(); for (int i = 1 ; i <= n; i++) { if (ins[i]==0 ){ q.offer(i); } } int res=0 ; int total=0 ; while (!q.isEmpty()){ int size=q.size(); while (size-->0 ){ int cur=q.poll(); total++; for (Integer next : graph[cur]) { ins[next]--; if (ins[next]==0 ){ q.offer(next); } } } res++; } return total==n ? res : -1 ; }
1557. Minimum Number of Vertices to Reach All Nodes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public List<Integer> findSmallestSetOfVertices (int n, List<List<Integer>> edges) { int [] ins=new int [n]; for (List<Integer> edge : edges) { int from=edge.get(0 ); int to=edge.get(1 ); ins[to]++; } List<Integer> res=new ArrayList <>(); for (int i = 0 ; i < n; i++) { if (ins[i]==0 ){ res.add(i); } } return res; }
1203. Sort Items by Groups Respecting Dependencies 双重bfs topological sort,好题!
反思:
注意groupId可能不连贯
遇到报错不要乱改,先从简单的debug办法入手,不要一上来就大改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 public int [] sortItems(int n, int m, int [] group, List<List<Integer>> beforeItems) { for (int i = 0 ; i < n; i++) { if (group[i]==-1 ){ group[i]=m++; } } int [] itemIns=new int [n]; int [] groupIns=new int [m]; List<List<Integer>> nextItems=new ArrayList <>(); List<List<Integer>> nextGroups=new ArrayList <>(); for (int i = 0 ; i < n; i++) { nextItems.add(new ArrayList <>()); } for (int i = 0 ; i < m; i++) { nextGroups.add(new ArrayList <>()); } for (int to = 0 ; to < n; to++) { for (Integer from : beforeItems.get(to)) { itemIns[to]++; nextItems.get(from).add(to); if (group[from]!=group[to]){ groupIns[group[to]]++; nextGroups.get(group[from]).add(group[to]); } } } List<Integer> sortedItems=topologicalSort(itemIns,nextItems); List<Integer> sortedGroups=topologicalSort(groupIns,nextGroups); if (sortedItems==null || sortedGroups==null ){ return new int [0 ]; } List<Integer> res=new ArrayList <>(); Map<Integer,List<Integer>> groupToItems=new HashMap <>(); for (Integer item : sortedItems) { int groupId=group[item]; groupToItems.putIfAbsent(groupId,new ArrayList <>()); groupToItems.get(groupId).add(item); } for (Integer groupId : sortedGroups) { List<Integer> list=groupToItems.get(groupId); if (list!=null ){ for (Integer item : list) { res.add(item); } } } return res.stream().mapToInt(i->i).toArray(); } private List<Integer> topologicalSort (int [] ins, List<List<Integer>> next) { Deque<Integer> q=new LinkedList <>(); int len=ins.length; for (int i = 0 ; i < len; i++) { if (ins[i]==0 ){ q.offer(i); } } List<Integer> res=new ArrayList <>(); while (!q.isEmpty()){ int cur=q.poll(); res.add(cur); for (Integer to : next.get(cur)) { ins[to]--; if (ins[to]==0 ){ q.offer(to); } } } return res.size()==len ? res : null ; }
1334. Find the City With the Smallest Number of Neighbors at a Threshold Distance 法一: brute force bfs 很慢!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public int findTheCity (int n, int [][] edges, int distanceThreshold) { Map<Integer,Integer>[] neighbors=new Map [n]; for (int i = 0 ; i < n; i++) { neighbors[i]=new HashMap <>(); } for (int [] edge : edges) { int a=edge[0 ]; int b=edge[1 ]; neighbors[a].put(b,edge[2 ]); neighbors[b].put(a,edge[2 ]); } int res=0 ; int min=Integer.MAX_VALUE; for (int i = 0 ; i < n; i++) { int count=bfs(neighbors,n,i,distanceThreshold); if (count<=min){ min=count; res=i; } } return res; } private int bfs (Map<Integer,Integer>[] neighbors, int n, int start, int threshold) { PriorityQueue<int []> pq=new PriorityQueue <>((a,b)->(a[1 ]-b[1 ])); boolean [] visited=new boolean [n]; pq.offer(new int []{start,0 }); int res=-1 ; while (!pq.isEmpty()){ int [] cur=pq.poll(); int idx=cur[0 ]; int dist=cur[1 ]; if (dist>threshold){ break ; } if (visited[idx]){ continue ; } visited[idx]=true ; res++; for (Integer next : neighbors[idx].keySet()) { pq.offer(new int []{next,dist+neighbors[idx].get(next)}); } } return res; }
法二:floyd Time O(N^3)
Space O(N^2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public int findTheCity (int n, int [][] edges, int distanceThreshold) { int [][] dist=new int [n][n]; for (int i = 0 ; i < n; i++) { Arrays.fill(dist[i],10001 ); } for (int i = 0 ; i < n; i++) { dist[i][i]=0 ; } for (int [] edge : edges) { int a=edge[0 ]; int b=edge[1 ]; dist[a][b]=edge[2 ]; dist[b][a]=edge[2 ]; } for (int k = 0 ; k < n; k++) { for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < n; j++) { dist[i][j]=Math.min(dist[i][j],dist[i][k]+dist[k][j]); } } } int res=0 ; int min=Integer.MAX_VALUE; for (int i = 0 ; i < n; i++) { int count=0 ; for (int j = 0 ; j < n; j++) { if (dist[i][j]<=distanceThreshold){ count++; } } if (count<=min){ min=count; res=i; } } return res; }
1559. Detect Cycles in 2D Grid 注意:
无需关注length,只需关注是否成环(visited)
dfs while keeping track of last visited node
只需一个global visited即可,因为会判断值是否相同,不同的path并不会干扰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 char [][] grid;int row;int col;int [] dx=new int []{0 ,0 ,1 ,-1 };int [] dy=new int []{1 ,-1 ,0 ,0 };public boolean containsCycle (char [][] grid) { this .grid=grid; this .row=grid.length; this .col=grid[0 ].length; boolean found=false ; boolean [][] visited=new boolean [row][col]; a:for (int i=0 ; i<row; i++){ for (int j=0 ; j<col; j++){ if (!visited[i][j]){ if (dfs(i,j,-1 ,-1 ,visited)){ found=true ; break a; } } } } return found; } private boolean dfs (int i, int j, int px, int py, boolean [][] visited) { boolean res=false ; visited[i][j]=true ; for (int k=0 ; k<4 ; k++){ int x=i+dx[k]; int y=j+dy[k]; if (x>=0 && x<row && y>=0 && y<col && grid[x][y]==grid[i][j]){ if (x!=px || y!=py){ if (visited[x][y]){ return true ; } res|=dfs(x,y,i,j,visited); } } } return res; }