// Check structure of Watch Where You Step; assumes that syntax has been // checked already via, e.g., watch_syntax_bobr.ctd import java.util.*; class Node { public int id; // actual node number 0, ... , n-1 from input public int pre; // preorder number; assigned by algorithm public int comp; // component number; assigned by algorithm public ArrayList adj; // adjacency list public ArrayList members; // only for SCC construction public Node(int i) { id = i; adj = new ArrayList(); members = new ArrayList(); pre = -1; comp = -1; } } public class Watch_check_bobr { public static int n; public static int mat[][]; public static ArrayList[] adj; public static Node[] nd; // list of nodes for easy reference public static Stack S, P; public static int comp; public static int pre; public static boolean[] vis; public static Node[] scc; public static void main (String[] args) { Scanner in = new Scanner(System.in); n = in.nextInt(); mat = new int[n][n]; nd = new Node[n]; for (int i = 0; i < n; i++) { nd[i] = new Node(i); for (int j = 0; j < n; j++) { int t = in.nextInt(); mat[i][j] = t; if (t == 1) nd[i].adj.add(j); } } // make sure no loops at vertices: for (int i = 0; i < n; i++) { if (mat[i][i] == 1) { System.out.println("Loop at vertex "+i); System.exit(1); } } // make sure there is a (not necessarily simple) directed path // connecting all vertices. We know it's true within any // strongly-connected component, so we'll // compute the SCCs and then look for a path that contains every SCC. // (This is almost as hard as solving the contest problem.) // Try a different SCC algorithm than the one used in my solution, e.g., // https://en.wikipedia.org/wiki/Path-based_strong_component_algorithm) S = new Stack(); P = new Stack(); comp = 0; pre = 0; for (int i = 0; i < n; i++) { if (nd[i].pre < 0) dfs(i); } /* for (int i = 0; i < comp; i++) { System.out.print("Component "+i+": "); for (int j = 0; j < n; j++) { if (nd[j].comp == i) System.out.print(j+" "); } System.out.println(); } */ // Now construct a component graph and find longest path: scc = new Node[comp]; for (int i = 0; i < comp; i++) scc[i] = new Node(i); for (int i = 0; i < n; i++) { scc[nd[i].comp].members.add(i); for (Integer w : nd[i].adj) { if (!scc[nd[i].comp].adj.contains(nd[w].comp)) scc[nd[i].comp].adj.add(nd[w].comp); } } /* System.out.println("Components:"); for (int i = 0; i < comp; i++) { System.out.print(i+": "); for (Integer j : scc[i].members) { System.out.print(j+" "); } System.out.println(); } */ // Finally, find longest path. Do a topological sort on the scc graph... vis = new boolean[comp]; S = new Stack(); for (int i = 0; i < comp; i++) if (!vis[i]) ts(i); int sorted[] = new int[comp]; for (int i = 0; i < comp; i++) { sorted[i] = S.pop(); } // ... and then see if there is a continuous path connecting the // topologically-sorted vertices: int i = 0; for (int j = 1; j < comp; j++) { if (!scc[sorted[i]].adj.contains(sorted[j])) { System.out.println("No edge from component "+sorted[i]+ " to component "+sorted[j]); System.exit(1); } i = j; } System.exit(42); } public static void ts(int v) { vis[v] = true; for (Integer w : scc[v].adj) { if (!vis[w]) ts(w); } S.push(v); } public static void dfs(int v) { nd[v].pre = pre++; S.push(v); P.push(v); for (Integer w : nd[v].adj) { if (nd[w].pre < 0) { dfs(w); } else if (nd[w].comp < 0) { while (nd[P.peek()].pre > nd[w].pre) { P.pop(); } } } if (P.peek() == v) { Integer w = S.pop(); while (true) { if (nd[w].comp < 0) { nd[w].comp = comp; } if (w == v) { comp++; break; } w = S.pop(); } P.pop(); } } }