Punjab University College of Information Technology Renegades Contents 1 Graphs 1.1 Eulerian circuit / path . . . . . . . . 1.2 Bridges . . . . . . . . . . . . . . . . . 1.3 Articulation/Cut Point . . . . . . . . 1.4 Strongly Connected Components . 1.5 Minimum Spanning Tree (Kruskal) 1.6 Bellman Ford . . . . . . . . . . . . . 1.7 Dijkstra . . . . . . . . . . . . . . . . 1.8 Floyd Warshall . . . . . . . . . . . . 1.8.1 Printing shortest paths . . . 1.8.2 Diameter of graph . . . . . . 1.9 Path counting . . . . . . . . . . . . . 1.10 Max Flow . . . . . . . . . . . . . . . 1.11 Min max cost flow . . . . . . . . . . 2 Data Structures 2.1 Strings . . . . . . . . . . . . . . . . 2.1.1 KMP . . . . . . . . . . . . . 2.1.2 Suffix Array (empty) . . . 2.2 Trees . . . . . . . . . . . . . . . . . 2.2.1 Lowest Common Ancestor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 3 3 4 4 5 6 7 7 8 8 8 9 . . . . . 11 11 11 11 11 11 3 Dynamic Programming 12 3.1 Prefix 2d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.2 Max Sum Sub-Rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 4 Number Theory 13 4.1 Modulo Inverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 4.2 Combinatorics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 4.3 lcm gcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5 Misc 13 5.1 RMQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.2 Matrix Exponentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 6 Python 14 1 1 Graphs 1.1 Eulerian circuit / path An Eulerian Path is a path of edges that visits all the edges in a graph exactly once. Similarly, an Eulerian circuit is an Eulerian path which starts and ends on the same vertex. Here are conditions. Type Undirected Graph Directed Graph Eulerian circuit Every Vertex has an even degree Every Vertex has equal indegree and outdegree Eulerian path Either every Vertex has an even degree or exactly two edges have odd degree At most one vertex has outdegree - indegree = 1 and atmost one vertex has indegree - outdegree = 1 and all other vertices have equal in and out degree // to check for the direted graph list<int> path; bool pathExist(vector<int> in, vector<int> out, int n) { int startNodes = 0, endNodes = 0; for (int i = 0; i < n; i++) { if (out[i] - in[i] > 1 || in[i] - out[i] > 1) return false; else if (out[i] - in[i] == 1) startNodes++; else if (in[i] - out[i] == 1) endNodes++; } return (endNodes == 0 && startNodes == 0) || (endNodes == 1 && startNodes == 1); } void DFS(vector< vector<int> >& adj_list, int curr, vector<int>& out) { while (out[curr]) DFS(adj_list, adj_list[curr][--out[curr]], out); path.push_front(curr); } int findStartNode(vector<int> in, vector<int> out, int n) { int start = 0; for (int i = 0; i < n ; i++) { // Unique starting node. if (out[i] - in[i] == 1) return i; // Start at a node with an outgoing edge. if (out[i]) start = i; } return start; } void EulerPath(vector< vector<int> >& adj_list, int curr) { vector<int> out(adj_list.size(), 0), in(adj_list.size(), 0); for (int u = 0; u < adj_list.size(); u++) for (auto v : adj_list[u]) { 2 out[u]++; in[v]++; } if (!pathExist(in, out, adj_list.size())) return; int s = findStartNode(in, out, adj_list.size()); DFS(adj_list, s, out); } 1.2 Bridges Informally, the problem is formulated as follows: given a map of cities connected with roads, find all "important" roads, i.e. roads which, when removed, cause disappearance of a path between some pair of cities. int n, timer; // number of nodes vector <int> visited(n, false); vecotr <vector<int> > adj(n, vector<int>()); vector<int> tin(n), low(n); void dfs(int v, int p) { visited[v] = true; tin[v] = low[v] = ++timer; for (int u : adj[v]) if (u == p) continue; // direct edge to parent else if (visited[u]) // back edge low[v] = min(low[v], tin[u]); else { // forward edge dfs(u, v); low[v] = min(low[v], low[u]); if (low[u] > tin[v]) // bridge found process_the_bridge(v, u); // your logic } } int find_bridges() { for (int i = 0; i < n; i++) if (!visited[i]) dfs (i, -1); } 1.3 Articulation/Cut Point int n, timer; vector <int> visited(n, false); vecotr <vector<int> > adj(n, vector<int>()); vector<int> tin(n), low(n); void dfs(int v, int p) { visited[v] = true; tin[v] = in[v] = ++timer; int children = 0; for (int u : adj[v]) if (u == p) continue; else if (visited[u]) low[v] = min(low[v], tin[u]); 3 else { dfs(u, v); children++; low[v] = min(low[v], low[u]) if (low[u] >= tin[v] and p != 1) // excluding root process_the_cutpoint(v); } if (p == -1 and children > 1) process_the_cutpoint(v); } void find_cutpoints() { for (int i = 0; i < n; i++) if (!visited[i]) dfs(i, -1); } 1.4 Strongly Connected Components const int n = 7; stack<int> s; bool onStack[n] = {0}; bool visited[n] = {0}; int timer, sccCount; int tin[n], low[n]; vector <vector<int>> adj_list(n); void dfs(int v) { // Do some book keeping stuff visited[v] = true; s.push(v); onStack[v] = true; tin[v] = low[v] = ++timer; for (int u : adj_list[v]) { if (!visited[u]) dfs(u); if (onStack[u]) low[v] = min(low[v], low[u]); } // after exploring all the adjacent nodes of v if (tin[v] == low[v]) { // we are at the start of scc, empty the stack till the start of the s int u; while (1) { u = s.top(); s.pop(); onStack[u] = false; low[u] = tin[v]; printf("%d ", u); if (u == v) { puts(""); break; } } sccCount++; } } void tarjan_scc() { for (int i = 0; i < n; i++) if (!visited[i]) dfs(i);} 1.5 Minimum Spanning Tree (Kruskal) 4 const int MAX = 1e4 + 5; int id[MAX], nodes, edges; pair <long long, pair<int, int> > p[MAX]; void initialize() { for (int i = 0; i < MAX; ++i) id[i] = i; } int root(int x) { while (id[x] != x) { id[x] = id[id[x]]; x = id[x]; } return x; } void union1(int x, int y) { int p = root(x); int q = root(y); id[p] = id[q]; } long long kruskal(pair<long long, pair<int, int> > p[]) { int x, y; long long cost, minimumCost = 0; sort(p, p + edges); for (int i = 0; i < edges; ++i) { // Selecting edges one by one in increasing order from the beginning x = p[i].second.first; y = p[i].second.second; cost = p[i].first; if (root(x) != root(y)) // Check if the selected edge is creating a cycle or not { minimumCost += cost; union1(x, y); } } return minimumCost; } 1.6 Bellman Ford struct edge { int a, b, cost; }; int n, m, v; vector<edge> e; const int INF = 1000000000; void solve() { vector<int> d (n, INF); 5 d[v] = 0; vector<int> p (n - 1); int x; for (int i = 0; i < n; ++i) { x = -1; for (int j = 0; j < m; ++j) if (d[e[j].a] < INF) if (d[e[j].b] > d[e[j].a] + e[j].cost) { d[e[j].b] = max (-INF, d[e[j].a] + e[j].cost); p[e[j].b] = e[j].a; x = e[j].b; } if (x == -1) break; } if (x == -1) cout << "No negative cycle from " << v; else { int y = x; for (int i = 0; i < n; ++i) y = p[y]; vector<int> path; for (int cur = y ;; cur = p[cur]) { path.push_back (cur); if (cur == y && path.size() > 1) break; } reverse (path.begin(), path.end()); cout << "Negative cycle: "; for (int i = 0; i < path.size(); ++i) cout << path[i] << ’ ’; } } 1.7 Dijkstra vector <vector< pii >> adj_list(maxNodes); vector <vector<int> > dijkstra(int source) { vector <int> d(maxNodes, 99999), p(maxNodes); vector <bool> done(maxNodes, false); p[source] = source; d[source] = 0; priority_queue <pii, vector<pii>, greater<pii>> pq; pq.push({0, source}); while(!pq.empty()){ int curr, len, to; curr = pq.top().second; pq.pop(); if (done[curr]) continue; done[curr] = true; for (auto edge: adj_list[curr]){ tie(to, len) = edge; if (d[curr] + len < d[to]){ d[to] = d[curr] + len; 6 p[to] = curr; pq.push({d[to], to}); } } } return {d, p}; } void printPath(vector<int>& p, int s){ if (p[s] == s) printf ("%d ---> ", s); else printPath(p, p[s]), printf ("%d ---> ", s); } int main(){ auto ans = dijkstra(2); for (auto d: ans[0]) cout << d << ’ ’; puts(""); for (int i=0; i<maxNodes; i++) if(ans[0][i] != 99999) printPath(ans[1], i), puts(" END"); return 0; } 1.8 Floyd Warshall for (int k = 0; k < n; ++k) for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) if (d[i][k] < INF && d[k][j] < INF) d[i][j] = min(d[i][j], d[i][k] + d[k][j]); // It is assumed that if there is no edge between any two vertices i and j, // then the matrix at d[i][j] contains a large number (large enough so that // it is greater than the length of any path in this graph). 1.8.1 Printing shortest paths // let p be a 2D parent matrix, where p[i][j] is the last vertex before j // on a shortest path from i to j, i.e. i -> ... -> p[i][j] -> j for (int i = 0; i < V; i++) for (int j = 0; j < V; j++) p[i][j] = i; // initialize the parent matrix for (int k = 0; k < V; k++) for (int i = 0; i < V; i++) for (int j = 0; j < V; j++) // this time, we need to use if statement if (AdjMat[i][k] + AdjMat[k][j] < AdjMat[i][j]) { AdjMat[i][j] = AdjMat[i][k] + AdjMat[k][j]; p[i][j] = p[k][j]; // update the parent matrix } // when we need to print the shortest paths, we can call the method below: void printPath(int i, int j) { if (i != j) printPath(i, p[i][j]); printf(" %d", j); } 7 1.8.2 Diameter of graph The diameter of a graph is defined as the maximum shortest path distance between any pair of vertices of that graph. To find the diameter of a graph, we first find the shortest path between each pair of vertices (i.e. the APSP problem). The maximum distance found is the diameter of the graph. However, we can only do this for a small graph with V <= 400. 1.9 Path counting vector<bool> visited(6, false); vector<int> dp(6, 0); vector <vector<int>> adj_list(6); int count_path(int v, int t) { if (v == t) return 1; if (dp[v]) return dp[v]; visited[v] = true; for (auto u : adj_list[v]) if (!visited[u]) dp[v] += count_path(u, t); visited[v] = false; return dp[v]; } vector <int> order; void topological_sort(int v) { visited[v] = true; for (auto u : adj_list[v]) if (!visited[u]) topological_sort(u); order.push_back(v); } int solve(int v, int t) { order.clear(); visited.assign(6, false); topological_sort(v); reverse(order.begin(), order.end()); vector<int> dp(6, 0); dp[v] = 1; for (auto u : order) for (auto w : adj_list[u]) dp[w] += dp[u]; return dp[t]; } 1.10 Max Flow #define vi vector<int> int n; vector<vi> capacity, adj_list; 8 int bfs(int s, int t, vi& parent){ fill(parent.begin(), parent.end(), -1); parent[s] = -2; queue< pair<int, int> > q; q.push({s, inf}); int cur, flow; while(!q.empty()){ tie(cur, flow) = q.front(); q.pop(); for (auto nxt : adj_list[curr]) if (parent[nxt] == -1 and capacity[cur][next]){ parent[nxt] = cur; int new_flow = min(flow, capacity[cur][nxt]; if (nxt == t) return new_flow; q.push({nxt, new_flow}); } } return 0; } int max_flow(int s, int t) { int flow = 0, new_flow; vi parent(n); while(new_flow = bfs(s, t, parent)){ flow += new_flow; int cur = t; while(cur != s){ int prev = parent[cur]; capacity[prev][cur] -= new_flow; capacity[cur][prev] += new_flow; cur = prev; } } return flow; } 1.11 Min max cost flow const ll INF = numeric_limits<ll>::max() / 4; typedef vector<ll> VL; struct MCMF { int N; vector<vi> ed, red; vector<VL> cap, flow, cost; vi seen; VL dist, pi; vector<pii> par; MCMF(int N) : N(N), ed(N), red(N), cap(N, VL(N)), flow(cap), cost(cap), seen(N), dist(N), pi(N), par(N) {} 9 void addEdge(int from, int to, ll cap, ll cost) { this->cap[from][to] = cap; this->cost[from][to] = cost; ed[from].push_back(to); red[to].push_back(from); } void path(int s) { fill(all(seen), 0); fill(all(dist), INF); dist[s] = 0; ll di; __gnu_pbds::priority_queue<pair<ll, int>> q; vector<decltype(q)::point_iterator> its(N); q.push({0, s}); auto relax = [&](int i, ll cap, ll cost, int dir) { ll val = di - pi[i] + cost; if (cap && val < dist[i]) { dist[i] = val; par[i] = {s, dir}; if (its[i] == q.end()) its[i] = q.push({ -dist[i], i}); else q.modify(its[i], { -dist[i], i}); } }; while (!q.empty()) { s = q.top().second; q.pop(); seen[s] = 1; di = dist[s] + pi[s]; for (int i : ed[s]) if (!seen[i]) relax(i, cap[s][i] - flow[s][i], cost[s][i], 1); for (int i : red[s]) if (!seen[i]) relax(i, flow[i][s], -cost[i][s], 0); } rep(i, 0, N) pi[i] = min(pi[i] + dist[i], INF); } pair<ll, ll> maxflow(int s, int t) { ll totflow = 0, totcost = 0; while (path(s), seen[t]) { ll fl = INF; for (int p, r, x = t; tie(p, r) = par[x], x != s; x = p) fl = min(fl, r ? cap[p][x] - flow[p][x] : flow[x][p]); totflow += fl; for (int p, r, x = t; tie(p, r) = par[x], x != s; x = p) if (r) flow[p][x] += fl; else flow[x][p] -= fl; } rep(i, 0, N) rep(j, 0, N) totcost += cost[i][j] * flow[i][j]; return {totflow, totcost}; } // If some costs can be negative, call this before maxflow: void setpi(int s) { // (otherwise, leave this out) fill(all(pi), INF); pi[s] = 0; int it = N, ch = 1; ll v; 10 while (ch-- && it--) rep(i, 0, N) if (pi[i] != INF) for (int to : ed[i]) if (cap[i][to]) if ((v = pi[i] + cost[i][to]) < pi[to]) pi[to] = v, ch = 1; assert(it >= 0); // negative cost cycle } }; 2 Data Structures 2.1 Strings 2.1.1 KMP vector<int> prefix_kmp(string word, string sentence) { int n = sentence.size(); vector<int> pi(n, 0); for (int i = 0; i < n; i++) { int j = pi[i - 1]; while (j > 0 and word[i] != sentence[j] and j >= word.size()) j = pi[j - 1]; pi[i] = j + (word[i] == sentence[j]); } return pi; } 2.1.2 2.2 Suffix Array (empty) Trees 2.2.1 Lowest Common Ancestor class TreeAncestor { public: int log = 20; vector<int> depth; vector < vector<int> > table; void dfs(int curr, vector < vector<int> >& adj_list) { for (int i=1; i<=log; i++) table[curr][i] = table[table[curr][i-1]][i-1]; // update children depth and move on to them for (auto v : adj_list[curr]){ depth[v] = depth[curr] + 1; table[v][0] = curr; dfs(v, adj_list); } } TreeAncestor(int n, vector<int>& parent) { depth = vector<int>(n+1); table = vector<vector<int>>(n+1, vector<int>(log+1)); 11 vector < vector<int> > adj_list(n+1); int root; for (int i=0; i<parent.size(); i++) if (parent[i] == -1) root = i; else adj_list[parent[i]].push_back(i); depth[root] = 0; dfs(root, adj_list); } int getKthAncestor(int node, int k) { if (depth[node] < k) return -1; for (int i = 0; i <= log; i++) if (k & (1 << i)) node = table[node][i]; return node; } int getLCA(int a, int b){ if(depth[a] < depth[b]) swap(a, b); // make ’a’ the deeper node int k = depth[a] - depth[b]; a = getKthAncestor(a, k); // get same depth if (a==b) { return a; } // if b was same is an ancestor of a // moove both a and b with powers of 2 (below any commone ancesstor) for (int i=log-1; i>=0; i--) if (up[a][i] != up[b][i]){ a = up[a][i]; b = up[b][i]; } return up[a][0]; } }; 3 3.1 Dynamic Programming Prefix 2d // prefix sum REP(i, n) REP(j, m) prefix[i + 1][j + 1] = prefix[i + 1][j + 1] + prefix[i][j + 1] + prefix[i + 1][j] - prefix[i][j]; int ans = prefix[A][B] + prefix[a - 1][b - 1] - prefix[A][b - 1] - prefix[a - 1][B] 3.2 Max Sum Sub-Rectangle int n, grid[101][101]; int maxSubArraySum(int* arr) { int ans = INT_MIN, a = 0; for (int i = 0; i < n; i++) { a += arr[i]; ans = max(ans, a); a = max(a, 0); } return ans; 12 } int main() { int rectSum, maxRectSum = INT_MIN; for (int l = 0; l < n; l++) { int runningArray[n] = {0}; for (int r = l; r < n; r++) { for (int i = 0; i < n; i++) runningArray[i] += grid[i][r]; rectSum = maxSubArraySum(runningArray); maxRectSum = max(rectSum, maxRectSum); } } printf("%d\n", maxRectSum); } return 0; } 4 4.1 Number Theory Modulo Inverse ll moduloInverse(ll base, ll p, ll mod) { ll identity = 1LL; while (p > 1) { if (p & 1) identity = (identity * 1LL * base) % mod; base = (base * 1LL * base) % mod; p /= 2; } return (identity * base * 1LL) % mod; } 4.2 4.3 Combinatorics Pn k = n( n + 1)/2 Pkn=0 2 k = n( n + 1)(2 n + 1)/6 ¢ Pkn=0 4 ¡ 5 k = ¡6 n + 15¢n4 + 10 n3 − n /30 k = 0 Pn x k = x n+1 − 1 /( x − 1) k=0 Pb k = (a + b)( b − a + 1)/2 Pkn=a 3 k = n2 ( n + 1)2 /4 ¢ Pkn=0 5 ¡ 6 k = 2¡n + 6 n5 + 5 n4 − n2 /12¢ k = 0 Pn kx k = x − ( n + 1) x n+1 + nx n+2 /( x − 1)2 k=0 lcm gcd ll gcd(ll a,ll b){ if(b==0) return a; else return gcd(b,a%b); } ll lcm(ll a,ll b){ return a/gcd(a,b)*b; } 5 5.1 Misc RMQ 13 #define better(a,b) A[a]<A[b]?(a):(b) int make_dp(int n) { // N log N REP(i,n) H[i][0]=i; for(int l=0,k; (k=1<<l) < n; l++) for(int i=0;i+k<n;i++) H[i][l+1] = better(H[i][l], H[i+k][l]); } int query_dp(int a, int b) { int l = __lg(b-a); return better(H[a][l], H[b-(1<<l)+1][l]); } 5.2 Matrix Exponentation template<class T> class Matrix{ public: vector< vector<T> > mat; // the contents of matrix as a 2D-vector int n_rows, n_cols; // number of rows and columns Matrix(vector< vector<T> > values) : mat(values), n_rows(values.size()), n_cols(values[0].size()) {} static Matrix identity_matrix(int n){ vector< vector<T> > values(n, vector<T>(n, 0)); for(int i = 0; i < n; i++) values[i][i] = 1; return values; } Matrix operator*(const Matrix<T> &other) const { int n = n_rows, m = other.n_cols; vector< vector<T> > result(n_rows, vector<T>(m, 0)); for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) for(int k = 0; k < n_cols; k++) { result[i][j] = (result[i][j] + mat[i][k] * other.mat[k][j]) % mod; (result[i][j] += mod) %= mod; } return Matrix(result); } }; Matrix<long long> M({ {1, 1}, {1, 0} }); auto ans = fast_exponentiation(M, n-1); cout << ans.mat[0][0] << ’\n’; 6 Python import itertools 14 stuff = [1, 2, 3] for L in range(len(stuff) + 1): for subset in itertools.combinations(stuff, L): print(list(subset)) def dfs(g, i): stack = [i] visited = set() while stack: start = stack[-1] if start not in visited: visited.add(start) for child in g[start]: stack.append(child) else: stack.pop() def isBipartite(g): col = [-1]*(len(g)) q = [] for i in range(len(g)): if (col[i] == -1): q.append([i, 0]) col[i] = 0 while len(q) != 0: p = q[0] q.pop(0) v = p[0] c = p[1] for j in g[v]: if (col[j] == c): return False if (col[j] == -1): if c == 1: col[j] = 0 else: col[j] = 1 q.append([j, col[j]]) return True g = [[1, 2], [0], [0, 3], [2]] print(isBipartite(g)) def bipartiteMatch(graph): matching = {} for u in graph: for v in graph[u]: if v not in matching: matching[v] = u break while 1: preds = {} unmatched = [] pred = dict([(u,unmatched) for u in graph]) for v in matching: del pred[matching[v]] 15 layer = list(pred) while layer and not unmatched: newLayer = {} for u in layer: for v in graph[u]: if v not in preds: newLayer.setdefault(v,[]).append(u) layer = [] for v in newLayer: preds[v] = newLayer[v] if v in matching: layer.append(matching[v]) pred[matching[v]] = v else: unmatched.append(v) if not unmatched: unlayered = {} for u in graph: for v in graph[u]: if v not in preds: unlayered[v] = None return (matching,list(pred),list(unlayered)) def recurse(v): if v in preds: L = preds[v] del preds[v] for u in L: if u in pred: pu = pred[u] del pred[u] if pu is unmatched or recurse(pu): matching[v] = u return 1 return 0 for v in unmatched: recurse(v) def min_vertex_cover(left_v, right_v): data_hk = bipartiteMatch(left_v) print(data_hk) left_mis = data_hk[1] right_mis = data_hk[2] mvc = left_v.copy() mvc.update(right_v) for v in left_mis: del(mvc[v]) for v in right_mis: del(mvc[v]) return mvc leftv = {’a’: [1, 3], ’c’: [1, 3], ’d’: [3, 6], ’h’: [8], ’i’: [8]} rightv = {1: [’a’, ’c’], 3: [’a’, ’c’, ’d’], 6: [’d’], 8: [’h’, ’i’]} print(min_vertex_cover(leftv, rightv)) def make_set : # disjoint set for v in range(n + 1): parent[v] = v 16 size[v] = 1 def find_set(v): if (v == parent[v]): return v parent[v] = find_set(parent[v]) return parent[v] def union_sets(a, b): a = find_set(a) b = find_set(b) if (a != b): if (size[a] < size[b]): a, b = b, a parent[b] = a size[a] += size[b] n, parent, size = 5, [None] * (n + 1), [None] * (n + 1) make_set(n) def rotate_a_matrix(a) : n = len(a) for r in range(n//2): for c in range(r, n - r - 1): a[r][c], a[c][n-1-r], a[n-1-r][n-1-c], a[n-1-c][r] = a[n-1-c][r], a[r][c], a[c] a[r][c], a[c][n-1-r], a[n-1-r][n-1-c], a[n-1-c][r] = a[c][n-1-r], a[n-1-r][n-1def kadane(arr, start, finish, n): # Largest sum submatrix Sum = 0 maxSum = -999999999999 i = None finish[0] = -1 local_start = 0 for i in range(n): Sum += arr[i] if Sum < 0: Sum = 0 local_start = i + 1 elif Sum > maxSum: maxSum = Sum start[0] = local_start finish[0] = i if finish[0] != -1: return maxSum maxSum = arr[0] start[0] = finish[0] = 0 for i in range(1, n): if arr[i] > maxSum: maxSum = arr[i] start[0] = finish[0] = i return maxSum def findMaxSum(M): global ROW, COL maxSum, finalLeft = -999999999999, None finalRight, finalTop, finalBottom = None, None, None left, right, i = None, None, None temp = [None] * ROW Sum = 0 17 start = [0] finish = [0] for left in range(COL): temp = [0] * ROW for right in range(left, COL): for i in range(ROW): temp[i] += M[i][right] Sum = kadane(temp, start, finish, ROW) if Sum > maxSum: maxSum = Sum finalLeft = left finalRight = right finalTop = start[0] finalBottom = finish[0] print("(Top, Left)", "(", finalTop, finalLeft, ")") print("(Bottom, Right)", "(", finalBottom, finalRight, ")") print("Max sum is:", maxSum) ROW = 4 COL = 5 M = [[1, 2, -1, -4, -20], [-8, -3, 4, 2, 1], [3, 8, 10, 1, 3], [-4, -1, 1, 7, -6]] n = rows = 10 # Flood Fill m = columns = 10 a = [] # input array q = [] four = [(1, 0), (-1, 0), (0, 1), (0, -1)] eight = [(-1, -1), (-1, 0), (-1, 1),(0, -1), (0, 1), (1, -1), (1, 0), (1, 1)] for i in range(1, n): for j in range(1, m): if a[i][j] == ’.’: q.append((i, j)) while q: x, y = q.pop() a[x][y] = ’#’ for dx, dy in four: if a[x + dx][y + dy] == ’.’: q.append((x + dx, y + dy)) def fastSieve(n): r = [False, True] * (n//2) + [True] r[1], r[2] = False, True for i in range(3, int(1 + n**0.5), 2): if r[i]: r[i*i::2*i] = [False] * ((n+2*i-1-i*i)//(2*i)) return r def factors(n): return list(set(reduce(list._add_, ([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))) 18 from math import inf # segment tree n, k = map(int, input().split()) a = list(map(int, input().split())) t = [inf] * (4 * n) # initial array, current vertex(1), array left(0), array right(n - 1) def build(a, v, tl, tr): if tl == tr: t[v] = a[tl] else: tm = (tl + tr) // 2 build(a, v * 2, tl, tm) build(a, v * 2 + 1, tm + 1, tr) t[v] = min(t[v * 2], t[v * 2 + 1]) # current vertex(1), array left(0), array right(n - 1), query left, query right (0 indexed) def query(v, tl, tr, l, r): if l > r: return inf if l == tl and r == tr: return t[v] tm = (tl + tr) // 2 return min(query(v * 2, tl, tm, l, min(r, tm)), query(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r)) # current vertex(1), array left(0), array right(n - 1), position (0 indexed), new value def update(v, tl, tr, pos, new_val): if tl == tr: t[v] = new_val else: tm = (tl + tr) // 2 if pos <= tm: update(v * 2, tl, tm, pos, new_val) else: update(v * 2 + 1, tm + 1, tr, pos, new_val) t[v] = min(t[v * 2], t[v * 2 + 1]) build(a, 1, 0, n - 1) n = int(input()) # count subarrays with xor a = list(map(int, input().split())) sq=[] p=0 while p*p<=4*10**5: sq.append(p*p) p+=1 occ = [0] * (2 * n) # number of times each element occured in the xor prefix array occ[0] = 1 # 0 obviously occured 1 times already if we take empty subarray c = 0 # count for subarrays with xor equal to any value is sq x = 0 # prefix xor uptill i for i in range(n): x ^= a[i] for j in sq: if j ^ x < 2 * n: c += (occ[j ^ x]) occ[x] += 1 print(c) from bisect import bisect_left # Longest increasing subsequence in nlgn 19 class Solution: def lengthOfLIS(self, nums: List[int]) -> int: ans = [nums[0]] for i in range(1, len(nums)): if nums[i] > ans[-1]: ans.append(nums[i]) else: ind = bisect_left(ans, nums[i]) ans[ind] = nums[i] return len(ans) print((999999).bit_length()) # find number of bits required to store an integer print(format(8, ’018b’)) # convert decimal to binary def ConvertDecimalToBaseX(num, x): if num == 0: return [0] digits = [] while num: digits.append(int(num % x)) num //= x return digits[::-1] def ConvertBaseXToDecimal(num, CurrBase): ans = 0 for i in map(int, num): ans = CurrBase * ans + i return ans def is_square(apositiveint): x = apositiveint // 2 seen = set([x]) while x * x != apositiveint: x = (x + (apositiveint // x)) // 2 if x in seen: return False seen.add(x) return True 20