diff --git a/caderno.pdf b/caderno.pdf index ec8f0d360fd18a194fae9d1448a4269a19a65092..df4efc6e241440cbb102cc7850d3e8487d05652a 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/caderno/caderno.tex b/caderno/caderno.tex index 116c6e61665146a51579362b37759e57decdc148..0e3a8e4ffd203ea7a4224774beac4a83d383caa2 100644 --- a/caderno/caderno.tex +++ b/caderno/caderno.tex @@ -287,11 +287,6 @@ para $a$ e $m$ coprimos. \subsection{Stoer-Wagner} \importsource{stoer-wagner.h} -\subsection{SPFA*} - -\subsection{BFS 0-1} -\importsource{bfs01.h} - \subsection{Emparelhamento estável} \begin{tabular}{l} \hline @@ -300,9 +295,11 @@ para $a$ e $m$ coprimos. \end{tabular} \importsource{stable-matching.h} -\subsection{Fluxo máximo*} +\subsection{Fluxo máximo} +\importsource{ffek.h} -\subsection{Fluxo de custo mínimo*} +\subsection{Fluxo de custo mínimo} +\importsource{ffekmincost.h} \subsection{Busca em profundidade recursiva} \importsource{dfsrec.h} @@ -313,23 +310,26 @@ para $a$ e $m$ coprimos. \subsection{Busca em largura} \importsource{bfs.h} -\subsection{Conectado*} -\importsource{connected.cpp} +\subsection{Busca em largura 0-1} +\importsource{bfs01.h} -\subsection{Componentes fortes -- Tarjan*} -\importsource{tarjan.cpp} +\subsection{Componentes fortes -- Tarjan} +\importsource{tarjan.h} -\subsection{Componentes fortes -- Kosaraju*} -\importsource{kosaraju.cpp} +\subsection{Componentes fortes -- Kosaraju} +\importsource{kosaraju.h} \subsection{Caminho mínimo -- Dijkstra} \importsource{dijkstra.h} -\subsection{Caminho mínimo -- Bellman-Ford*} -\importsource{bellman-ford.cpp} +\subsection{Caminho mínimo -- Bellman-Ford} +\importsource{bellman-ford.h} + +\subsection{Caminho mínimo -- SPFA} +\importsource{spfa.h} -\subsection{Caminhos mínimos -- Floyd-Warshall*} -\importsource{floyd-warshall.cpp} +\subsection{Caminhos mínimos -- Floyd-Warshall} +\importsource{floyd-warshall.h} \subsection{Ordenação Topológica} \importsource{topo.h} @@ -340,12 +340,11 @@ para $a$ e $m$ coprimos. \subsection{Árvore geradora mínima -- Kruskal} \importsource{kruskal.h} -\subsection{Ascensão binária*} -\importsource{binary-lifting.cpp} - -\subsection{Menor anc. comum -- Ancensão binária*} +\subsection{Ascensão binária} +\importsource{bl.h} -\subsection{Menor anc. comum -- Dec. pesado-leve*} +\subsection{Menor anc. comum -- Ancensão binária} +\importsource{bllca.h} \subsection{Decomposição pesado-leve} \begin{tabular}{l|l} @@ -368,9 +367,11 @@ para $a$ e $m$ coprimos. \subsection{Menor anc. comum -- Dec. raiz quad.} \importsource{stdtlca.h} -\subsection{Empar. máximo bipartido -- Kuhn*} +\subsection{Empar. máximo bipartido -- Kuhn} +\importsource{kuhn.h} -\subsection{Empar. máximo bipartido -- Hopcroft*} +\subsection{Empar. máximo bipartido -- Hopcroft} +\importsource{hopcroft.h} \section{Matemática} @@ -433,8 +434,61 @@ ax + by = c \end{tabular} \importsource{factorize.h} -\subsection{Crivo de Eratóstenes*} -\importsource{sieve-of-eratosthenes.cpp} +\subsection{Crivo de Eratóstenes} +\begin{tabular}{l} + \hline + $\bigO(n \lg\lg n)$ \\ +\hline +\end{tabular} +\importsource{sieve.h} + +\subsection{Crivo de número de divisores} +\begin{tabular}{l} + \hline + $\bigO(n \lg n)$ \\ +\hline +\end{tabular} +\importsource{divisors.h} + +\subsection{Crivo de soma dos divisores} +\begin{tabular}{l} + \hline + $\bigO(n \lg n)$ \\ +\hline +\end{tabular} +\importsource{sumdivsieve.h} + +\subsection{Totiente de Euler} +\begin{tabular}{l} + \hline + $\bigO(n \lg \lg n)$ \\ +\hline +\end{tabular} +\importsource{euler-totient.h} + +\subsection{Crivo de soma dos divisores} +\begin{tabular}{l} + \hline + $\bigO(n \lg n)$ \\ +\hline +\end{tabular} +\importsource{sumdivsieve.h} + +\subsection{Crivo de maior divisor primo} +\begin{tabular}{l} + \hline + $\bigO(n \lg n)$ \\ +\hline +\end{tabular} +\importsource{bigpsieve.h} + +\subsection{Crivo linear} +\begin{tabular}{l} + \hline + $\bigO(n)$ \\ +\hline +\end{tabular} +\importsource{linearsieve.h} \subsection{Exponenciação binária*} \importsource{binary-pow.h} @@ -448,9 +502,6 @@ ax + by = c \subsection{Teorema chinês do resto*} -\subsection{Totiente de Euler*} -\importsource{euler-totient.h} - \subsection{Fibonacci*} \subsection{Teorema chinês do resto generalizado*} diff --git a/fontes/acs.h b/fontes/acs.h index 4357d14f88e0dda436c0135bdc5bc90b2506609e..03c52dbeb9a7d68817f6ced4cfbee301f3aa197c 100644 --- a/fontes/acs.h +++ b/fontes/acs.h @@ -1,67 +1,67 @@ struct node { - int p, pc, depth, lnk, out, occ; - bool leaf; - vector<int> nxt, go, ix; + int p, pc, depth, lnk, out, occ; + bool leaf; + vector<int> nxt, go, ix; - node() : p (0), pc (0), depth (-1), - lnk (-1), out (-1), occ (0), - leaf (false), nxt (S, -1), go (S, -1) {} + node() : p (0), pc (0), depth (-1), + lnk (-1), out (-1), occ (0), + leaf (false), nxt (S, -1), go (S, -1) {} }; vector<node> aca (1); void ins(string ne, int ix) { - int u = 0; - for (int i = 0; i < ne.size(); i++) { - int ch = to_i(ne[i]); - if (aca[u].nxt[ch] == -1) { - aca[u].nxt[ch] = aca.size(); - node n; n.p = u; n.pc = ch; n.depth = i; - aca.push_back(n); - } - u = aca[u].nxt[ch]; + int u = 0; + for (int i = 0; i < ne.size(); i++) { + int ch = to_i(ne[i]); + if (aca[u].nxt[ch] == -1) { + aca[u].nxt[ch] = aca.size(); + node n; n.p = u; n.pc = ch; n.depth = i; + aca.push_back(n); } - aca[u].leaf = true; - aca[u].ix.push_back(ix); + u = aca[u].nxt[ch]; + } + aca[u].leaf = true; + aca[u].ix.push_back(ix); } int go(int u, int c); int link(int u) { - if (aca[u].lnk != -1) { return aca[u].lnk; } - if (u == 0 || aca[u].p == 0) { return aca[u].lnk = 0; } - return aca[u].lnk = go(link(aca[u].p), aca[u].pc); + if (aca[u].lnk != -1) { return aca[u].lnk; } + if (u == 0 || aca[u].p == 0) { return aca[u].lnk = 0; } + return aca[u].lnk = go(link(aca[u].p), aca[u].pc); } int go(int u, int c) { - if (aca[u].go[c] != -1) { return aca[u].go[c]; } - if (aca[u].nxt[c] != -1) - return aca[u].go[c] = aca[u].nxt[c]; - if (u == 0) { return aca[u].go[c] = 0; } - return aca[u].go[c] = go(link(u), c); + if (aca[u].go[c] != -1) { return aca[u].go[c]; } + if (aca[u].nxt[c] != -1) + return aca[u].go[c] = aca[u].nxt[c]; + if (u == 0) { return aca[u].go[c] = 0; } + return aca[u].go[c] = go(link(u), c); } int out(int u) { - if (aca[u].out != -1) { return aca[u].out; } - int v = link(u); - if (v == 0 || aca[v].leaf) { return aca[u].out = v; } - return aca[u].out = out(v); + if (aca[u].out != -1) { return aca[u].out; } + int v = link(u); + if (v == 0 || aca[v].leaf) { return aca[u].out = v; } + return aca[u].out = out(v); } vector<int> occ (N); vector<vector<int>> occix (N); void process(string hay) { - int u = 0; - for (int i = 0; i < hay.size(); i++) { - int ch = to_i(hay[i]); - u = go(u, ch); - for (int v = u; v != 0; v = out(v)) { - for (auto ix : aca[v].ix) - // match at (i - aca[v].depth), O(len + ans) - occix[ix].push_back(i - aca[v].depth); - aca[v].occ++; - } + int u = 0; + for (int i = 0; i < hay.size(); i++) { + int ch = to_i(hay[i]); + u = go(u, ch); + for (int v = u; v != 0; v = out(v)) { + for (auto ix : aca[v].ix) + // match at (i - aca[v].depth), O(len + ans) + occix[ix].push_back(i - aca[v].depth); + aca[v].occ++; } - for (int u = 0; u < aca.size(); u++) - for (auto ix : aca[u].ix) - // number of matches, O(len) - occ[ix] += aca[u].occ; + } + for (int u = 0; u < aca.size(); u++) + for (auto ix : aca[u].ix) + // number of matches, O(len) + occ[ix] += aca[u].occ; } diff --git a/fontes/bellman-ford.cpp b/fontes/bellman-ford.cpp deleted file mode 100644 index ce1267b22b20c9b1d2c90e8b8d885dd5afcfffc9..0000000000000000000000000000000000000000 --- a/fontes/bellman-ford.cpp +++ /dev/null @@ -1,22 +0,0 @@ -struct edge { int u, v, w; }; -vector<edge> edges; -vi dist (N); - -int bellman_ford (int source, int destination, int N) { - fill(dist.begin(), dist.begin() + N, oo); - dist[source] = 0; - - for (int i = 0; i < N; i++) - for (auto e : edges) - if (dist[e.u] != oo && - dist[e.v] > dist[e.u] + e.w) - dist[e.v] = dist[e.u] + e.w; - - // Verificação de ciclos negativos - for (auto e : edges) - if (dist[e.u] != oo && - dist[e.v] > dist[e.u] + e.w) - return -oo; - - return dist[destination]; -} diff --git a/fontes/bellman-ford.h b/fontes/bellman-ford.h new file mode 100644 index 0000000000000000000000000000000000000000..7a95d6ecd05acb6aa40bfa66d79e5aa92e100aeb --- /dev/null +++ b/fontes/bellman-ford.h @@ -0,0 +1,16 @@ +struct edge { int u, v, w; }; +vector<edge> edges; +vector<int> d (N, oo); + +int bellman_ford(int src, int dest, int n) { + d[src] = 0; + for (int i = 0; i < n - 1; i++) + for (auto e : edges) + if (d[e.u] != oo && d[e.v] > d[e.u] + e.w) + d[e.v] = d[e.u] + e.w; + // Verificação de ciclos negativos + for (auto e : edges) + if (d[e.u] != oo && d[e.v] > d[e.u] + e.w) + return -oo; + return d[dest]; +} diff --git a/fontes/bfs.h b/fontes/bfs.h index 97c924bb8cc97d5cbb593facfa1d5f49ac7476b7..a0dc89005601344db7fc6e4c57382a69982ce3ce 100644 --- a/fontes/bfs.h +++ b/fontes/bfs.h @@ -1,14 +1,14 @@ int explore(int u) { - int c = 0; - queue<int> q; - q.push(u); - while (!q.empty()) { - int u = q.front(); q.pop(); - for (int v : g[u]) if (!visited[v]) { - c++; - visited[v] = true; - q.push(v); - } + int c = 0; + queue<int> q; + q.push(u); + while (!q.empty()) { + int u = q.front(); q.pop(); + for (int v : g[u]) if (!visited[v]) { + c++; + visited[v] = true; + q.push(v); } - return c; + } + return c; } diff --git a/fontes/bfs01.h b/fontes/bfs01.h index ccb136133291fc23fc7e8f9bb9fe413ba60b40cd..cc1cac54d02ee9243d1aee71c57844bc20f25aab 100644 --- a/fontes/bfs01.h +++ b/fontes/bfs01.h @@ -1,20 +1,20 @@ vector<int> d (N, oo); void bfs01(int s) { - d[s] = 0; - deque<int> q; - q.push_front(s); - while (!q.empty()) { - int u = q.front(); - q.pop_front(); - for (auto [v, w] : g[u]) { - if (d[u] + w < d[v]) { - d[v] = d[u] + w; - if (w == 1) - q.push_back(v); - else - q.push_front(v); - } - } + d[s] = 0; + deque<int> q; + q.push_front(s); + while (!q.empty()) { + int u = q.front(); + q.pop_front(); + for (auto [v, w] : g[u]) { + if (d[u] + w < d[v]) { + d[v] = d[u] + w; + if (w == 1) + q.push_back(v); + else + q.push_front(v); + } } + } } diff --git a/fontes/bigpsieve.h b/fontes/bigpsieve.h new file mode 100644 index 0000000000000000000000000000000000000000..5f70a53494b1f564db9636599b039a7e15e0e76b --- /dev/null +++ b/fontes/bigpsieve.h @@ -0,0 +1,8 @@ +vector<int> big (N+1, 1); + +void biggest_prime_divisor(int n) { + for (int i = 1; i <= n; ++i) + if (big[i] == 1) + for (int j = i; j <= n; j += i) + big[j] = i; +} diff --git a/fontes/binary-lifting.cpp b/fontes/binary-lifting.cpp deleted file mode 100644 index 7b2579bfd181dd9a1d8ac4366885a60edd4a65ae..0000000000000000000000000000000000000000 --- a/fontes/binary-lifting.cpp +++ /dev/null @@ -1,72 +0,0 @@ -const int L = log2(N); -vector<int> depth (N, 0); -vector<int> wsum (N); -vector<vector<int>> weight (N, vector<int>(L+1)); -vector<vector<int>> up (N, vector<int>(L+1)); - -void bl_euler_tour (int u, int p, int w) { - up[u][0] = p; - weight[u][0] = w; - wsum[u] = wsum[p] + w; - depth[u] = depth[p] + 1; - for (auto e : graph[u]) if (e.vv != p) - bl_euler_tour(e.vv, u, e.ww); -} - -void bl_init (int u) { - depth[u] = 0; - bl_euler_tour(u, u, 0); - - // can be put into bl_euler_tour - // but will not work with cycles then - // (but could be useful for online) - for (int l = 0; l < L; l++) { - for (int u = 0; u < n; u++) { - int a = up[u][l]; - up[u][l+1] = up[a][l]; - weight[u][l+1] = max(weight[u][l], weight[a][l]); - } - } -} - -// also bl_lca, just return lca and exclude res -int bl_query_path (int a, int b) { - // if b is deeper than a, swap - if (depth[b] > depth[a]) { swap(a, b); } - - int res = 0; - - int diff = depth[a] - depth[b]; - for (int l = L; l >= 0; d--) if (diff & (1 << l)) { - res = max(res, weight[a][l]); - a = up[a][l]; - } - - if (a == b) { /* lca == a */ return res; } - - for (int l = L; l >= 0; d--) - if (up[a][l] != up[b][l]) { - res = max({ res, weight[a][l], weight[b][l] }); - a = up[a][l], b = up[b][l]; - } - - // lca == up[a][0] - return max({ res, weight[a][0], weight[b][0] }); -} - -int bl_get_one_down (int a, int b) { - // if b is deeper than a, swap - if (depth[b] > depth[a]) { swap(a, b); } - - int diff = max(depth[a] - depth[b] - 1, 0); - for (int l = L; l >= 0; d--) if (diff & (1 << l)) { - a = up[a][l]; - } - - return a; -} - -int bl_query_sum (int a, int b) { - int lca = bl_lca(a, b); - return (wsum[a] - wsum[lca]) + (wsum[b] - wsum[lca]); -} diff --git a/fontes/bl.h b/fontes/bl.h new file mode 100644 index 0000000000000000000000000000000000000000..b8f2093beb90b28074202e5af9ac54ce7dc82024 --- /dev/null +++ b/fontes/bl.h @@ -0,0 +1,44 @@ +const int L = log2(N); +vector<int> dep (N, 0); vector<ll> wsum (N); +vector<vector<ll>> weiop (N, vector<ll>(L+1)); +vector<vector<int>> up (N, vector<int>(L+1)); + +void bl_euler_tour(int u, int p, int w) { + up[u][0] = p; weiop[u][0] = w; + dep[u] = dep[p] + 1; wsum[u] = wsum[p] + w; + for (auto [v, w] : g[u]) if (v != p) + bl_euler_tour(v, u, w); +} + +void bl_init(int u, int n) { + dep[u] = 0; bl_euler_tour(u, u, 0); + // can be put into bl_euler_tour but it will not + // work with cycles (could be useful for online) + for (int l = 0; l < L; l++) + for (int u = 0; u < n; u++) { + int a = up[u][l]; + up[u][l+1] = up[a][l]; + weiop[u][l+1] = OP(weiop[u][l], weiop[a][l]); + } +} + +ll bl_op(int a, int b) { + if (!(dep[a] > dep[b])) { swap(a, b); } + ll res = NEUTRAL; + int diff = dep[a] - dep[b]; + for (int l = L; l >= 0; l--) if (diff & (1 << l)) { + res = OP(res, weiop[a][l]); a = up[a][l]; + } + if (a == b) { return res; } + for (int l = L; l >= 0; l--) + if (up[a][l] != up[b][l]) { + res = OP(res, OP(weiop[a][l], weiop[b][l])); + a = up[a][l], b = up[b][l]; + } + return OP(res, OP(weiop[a][0], weiop[b][0])); +} + +int bl_query_sum(int a, int b) { + int lca = bl_lca(a, b); + return (wsum[a] - wsum[lca]) + (wsum[b] - wsum[lca]); +} diff --git a/fontes/bllca.h b/fontes/bllca.h index 4bcd8b2e9966c3c319b5c500617103e7b0f88c14..6e450e45b167ca6cff508dc165a6428ebdc772c8 100644 --- a/fontes/bllca.h +++ b/fontes/bllca.h @@ -1,10 +1,18 @@ int bl_lca(int a, int b) { - if (!(depth[b] < depth[a])) { swap(a, b); } - int diff = depth[a] - depth[b]; - for (int l = L; l >= 0; l--) if (diff & (1 << l)) - a = up[a][l]; - if (a == b) { return a; } - for (int l = L; l >= 0; l--) if (up[a][l] != up[b][l]) - a = up[a][l], b = up[b][l]; - return up[a][0]; + if (!(dep[b] < dep[a])) { swap(a, b); } + int diff = dep[a] - dep[b]; + for (int l = L; l >= 0; l--) if (diff & (1 << l)) + a = up[a][l]; + if (a == b) { return a; } + for (int l = L; l >= 0; l--) if (up[a][l] != up[b][l]) + a = up[a][l], b = up[b][l]; + return up[a][0]; +} + +int bl_get_one_down(int a, int b) { + if (!(dep[b] < dep[a])) { swap(a, b); } + int diff = max(dep[a] - dep[b] - 1, 0); + for (int l = L; l >= 0; d--) if (diff & (1 << l)) + a = up[a][l]; + return a; } diff --git a/fontes/connected.cpp b/fontes/connected.cpp deleted file mode 100644 index 69913816958316b5a8a2f808b8a30e26644f412b..0000000000000000000000000000000000000000 --- a/fontes/connected.cpp +++ /dev/null @@ -1,28 +0,0 @@ -bool check_graph_connected_dfs() { - int start_vertex = 0; - visited = vector<int>(n_vertices, false); - dfs(start_vertex); - return (find(all(visited), 0) == visited.end()); -} - -bool check_graph_connected_bfs() { - int start_vertex = 0; - vector<int> visited(n_vertices, false); - queue<int> Q; - Q.push(start_vertex); - visited[start_vertex] = true; - - while (!Q.empty()) { - int i = Q.front(); - Q.pop(); - - for (auto node : graph[i]) { - if (!visited[node]) { - visited[node] = true; - Q.push(node); - } - } - } - - return find(all(visited), 0) == visited.end(); -} diff --git a/fontes/dfsrec.h b/fontes/dfsrec.h index 04b2dde8d72ce281d6fda4336e2d19bb21d1628d..ab58fc212d58219c10b57ba37c155ce42f6dd228 100644 --- a/fontes/dfsrec.h +++ b/fontes/dfsrec.h @@ -1,7 +1,7 @@ int explore(int u) { - visited[u] = true; - int c = 1; - for (int v : g[u]) if (!visited[v]) - c += explore(v); - return c; + visited[u] = true; + int c = 1; + for (int v : g[u]) if (!visited[v]) + c += explore(v); + return c; } diff --git a/fontes/dfsstack.h b/fontes/dfsstack.h index 3b8e6be2b217a36f1beb502b127b3b864ea1f73e..95d045893ccc4c6631d16608b59289a3abeb0dcb 100644 --- a/fontes/dfsstack.h +++ b/fontes/dfsstack.h @@ -1,14 +1,14 @@ int explore(int u) { - int c = 0; - stack<int> s; - s.push(u); - while (!s.empty()) { - int u = s.top(); s.pop(); - for (int v : g[u]) if (!visited[v]) { - c++; - visited[v] = true; - s.push(v); - } + int c = 0; + stack<int> s; + s.push(u); + while (!s.empty()) { + int u = s.top(); s.pop(); + for (int v : g[u]) if (!visited[v]) { + c++; + visited[v] = true; + s.push(v); } - return c; + } + return c; } diff --git a/fontes/dijkstra.h b/fontes/dijkstra.h index e70b8f22ee579ddb6994faf26b09f92777958520..8ebebe1849a2bad3315b26481fd0909661e56569 100644 --- a/fontes/dijkstra.h +++ b/fontes/dijkstra.h @@ -1,5 +1,6 @@ vector<ll> d (N); vector<bool> vis (N); vector<vector<int>> dag (N); + void dijkstra(int src, int dest) { fill(d.begin(), d.end(), oo); fill(vis.begin(), vis.end(), false); diff --git a/fontes/divisors.h b/fontes/divisors.h new file mode 100644 index 0000000000000000000000000000000000000000..45d4ed83f1d2a0dae39a3f6941f41998daea2e4f --- /dev/null +++ b/fontes/divisors.h @@ -0,0 +1,6 @@ +vector<int> divisors (N); +void number_of_divisors(int n) { + for (int i = 1; i <= n; ++i) + for (int j = i; j <= n; j += i) + divisors[j]++; +} diff --git a/fontes/euler-totient.h b/fontes/euler-totient.h index 0563c7a0990e227db3b29d7888b40059c757d477..a0368fcab385e3e93cb4683bb76e991bc8c5cc72 100644 --- a/fontes/euler-totient.h +++ b/fontes/euler-totient.h @@ -1,6 +1,5 @@ vector<ll> phi (N); -// O(n lg lg n) void totient(int n) { for (int i = 1; i <= n; i++) { phi[i] = i; } for (int i = 2; i <= n; i++) if (phi[i] == i) { diff --git a/fontes/ffek.h b/fontes/ffek.h new file mode 100644 index 0000000000000000000000000000000000000000..1131688cd9aae1f4cb8c5cb038ffc211cac0ae6a --- /dev/null +++ b/fontes/ffek.h @@ -0,0 +1,44 @@ +vector<vector<int>> res (N); +vector<int> ix (N), dist (N), par (N); +struct edge { int u, v, cap; }; +vector<edge> edges; + +void link(int u, int v, int c) { + res[u].pb(edges.size()); edges.pb({ u, v, c }); + res[v].pb(edges.size()); edges.pb({ v, u, 0 }); +} + +bool minimum_path(int s, int t) { + fill(dist.begin(), dist.end(), oo); dist[s] = 0; + queue<int> q; q.push(s); + while (!q.empty()) { + int u = q.front(); q.pop(); + if (u == t) { break; } + for (int i : res[u]) { + edge e = edges[i]; int v = e.v; + if (e.cap && dist[v] == oo) { + dist[v] = dist[u] + 1; + par[v] = u; ix[v] = i; + q.push(v); + } + } + } + return dist[t] < oo; +} + +pair<int, int> ffek(int s, int t) { + int min_cost = 0, max_flow = 0; + while (minimum_path(s, t)) { + int flow = oo; + for (int u = t; u != s; u = par[u]) { + flow = min(flow, edges[ix[u]].cap); + } + for (int u = t; u != s; u = par[u]) { + edges[ix[u] ].cap -= flow; + edges[ix[u]^1].cap += flow; + } + min_cost += flow * dist[t]; + max_flow += flow; + } + return { min_cost, max_flow }; +} diff --git a/fontes/ffekbfs.h b/fontes/ffekbfs.h deleted file mode 100644 index 56fcaa22ba0d06b68d9706b099399c8e1ddffa35..0000000000000000000000000000000000000000 --- a/fontes/ffekbfs.h +++ /dev/null @@ -1,18 +0,0 @@ -vector<int> ix (N), dist (N), par (N); -bool minimum_path(int s, int t) { - fill(dist.begin(), dist.end(), oo); dist[s] = 0; - queue<int> q; q.push(s); - while (!q.empty()) { - int u = q.front(); q.pop(); - if (u == t) { break; } - for (int i : res[u]) { - edge e = edges[i]; int v = e.v; - if (e.cap && dist[v] == oo) { - dist[v] = dist[u] + 1; - par[v] = u; ix[v] = i; - q.push(v); - } - } - } - return dist[t] < oo; -} diff --git a/fontes/ffekmincost.h b/fontes/ffekmincost.h new file mode 100644 index 0000000000000000000000000000000000000000..5490dd1d042e2b0cff38cd7a994e3c7719a2f639 --- /dev/null +++ b/fontes/ffekmincost.h @@ -0,0 +1,29 @@ +struct edge { int u, v, cap, cost; }; +vector<edge> edges; + +vector<int> queu (N), ix (N), dist (N), par (N); + +void link(int u, int v, int cap, int cost) { + res[u].push_back(edges.size()); + edges.push_back({ u, v, cap, cost }); + res[v].push_back(edges.size()); + edges.push_back({ v, u, 0, -cost }); +} + +bool minimum_path(int s, int t) { + fill(dist.begin(), dist.end(), oo); dist[s] = 0; + queue<int> q; q.push(s); + while (!q.empty()) { + int u = q.front(); q.pop(); + queu[u] = 0; + for (int i : res[u]) { + edge e = edges[i]; int v = e.v; + if (e.cap && dist[v] > dist[u] + e.cost) { + dist[v] = dist[u] + e.cost; + par[v] = u; ix[v] = i; + if (!queu[v]) { q.push(v); queu[v] = 1; } + } + } + } + return dist[t] < oo; +} diff --git a/fontes/ffekspfa.h b/fontes/ffekspfa.h deleted file mode 100644 index 1d6a97b4326042f8c88cdc8a76f5817dd192c827..0000000000000000000000000000000000000000 --- a/fontes/ffekspfa.h +++ /dev/null @@ -1,18 +0,0 @@ -vector<int> queu (N), ix (N), dist (N), par (N); -bool minimum_path(int s, int t) { - fill(dist.begin(), dist.end(), oo); dist[s] = 0; - queue<int> q; q.push(s); - while (!q.empty()) { - int u = q.front(); q.pop(); - queu[u] = 0; - for (int i : res[u]) { - edge e = edges[i]; int v = e.v; - if (e.cap && dist[v] > dist[u] + e.cost) { - dist[v] = dist[u] + e.cost; - par[v] = u; ix[v] = i; - if (!queu[v]) { q.push(v); queu[v] = 1; } - } - } - } - return dist[t] < oo; -} diff --git a/fontes/floyd-warshall.cpp b/fontes/floyd-warshall.cpp deleted file mode 100644 index a120f43f8296d86a51d39b0cc39f31ddd161251c..0000000000000000000000000000000000000000 --- a/fontes/floyd-warshall.cpp +++ /dev/null @@ -1,4 +0,0 @@ -for (int k = 0; k < N; k++) -for (int i = 0; i < N; i++) -for (int j = 0; j < N; j++) - dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); diff --git a/fontes/floyd-warshall.h b/fontes/floyd-warshall.h new file mode 100644 index 0000000000000000000000000000000000000000..510f550260ebf915fc71051dd5fb0b8905f104dc --- /dev/null +++ b/fontes/floyd-warshall.h @@ -0,0 +1,10 @@ +vector<vector<ll>> d (N, vector<ll>(N, oo)); + +int floydwarshall(int n) { + for (int u = 0; u < n; u++) + d[u][u] = 0; + for (int m = 0; m < n; m++) + for (int u = 0; u < n; u++) + for (int v = 0; v < n; v++) + d[u][v] = min(d[u][v], d[u][m] + d[m][v]); +} diff --git a/fontes/hld.h b/fontes/hld.h index b9fe87274900b617fa724fdef0171bb01451354f..9febdd92b860fe5ed324a84caa82b5d7a7eeb9fe 100644 --- a/fontes/hld.h +++ b/fontes/hld.h @@ -14,9 +14,7 @@ int hld_fill(int u, int p, int d = 0, ll w = 0) { } void hld(int u, int h) { - hds[u] = h; - ori[cix] = wei[u]; - ixs[u] = cix++; + hds[u] = h; ori[cix] = wei[u]; ixs[u] = cix++; if (hvy[u] != -1) hld(hvy[u], h); // continue chain for (auto [v, w] : g[u]) if (v != par[u] && v != hvy[u]) @@ -27,8 +25,7 @@ ll hld_op(int u, int v, bool edge_wei = 1) { ll ans = 0; for (; hds[u] != hds[v]; v = par[hds[v]]) { if (dep[hds[u]] > dep[hds[v]]) { swap(u, v); } - ans = OP(ans, - op_inclusive(ixs[hds[v]], ixs[v])); + ans = OP(ans, op_inclusive(ixs[hds[v]], ixs[v])); } if (dep[u] > dep[v]) { swap(u, v); } return OP(ans, op_inclusive(ixs[u] + edge_wei, ixs[v])); diff --git a/fontes/hopcroft.h b/fontes/hopcroft.h new file mode 100644 index 0000000000000000000000000000000000000000..ff08c1c758ef5dce60764032473bbf4e1c0b3eb5 --- /dev/null +++ b/fontes/hopcroft.h @@ -0,0 +1,40 @@ +vector<int> matchl (L, -1), matchr (R, -1); +vector<int> dist (L); + +bool bfs(int l) { + queue<int> Q; + for (int l = 0; l < L; l++) + if (matchl[l] == -1) { dist[l] = 0; Q.push(l); } + else { dist[l] = -1; } + bool ans = false; + while (!Q.empty()) { + int l = Q.front(); Q.pop(); + for (auto r : g[l]) + if (matchr[r] == -1) { + ans = true; + } else if (dist[matchr[r]] == -1) { + dist[matchr[r]] = dist[l] + 1; + Q.push(matchr[r]); + } + } + return ans; +} + +bool dfs(int l) { + if (l == -1) { return true; } + for (auto r : g[l]) + if (matchr[r] == -1 || dist[matchr[r]] == dist[l] + 1) + if (dfs(matchr[r])) { + matchr[r] = l; + matchl[l] = r; + return true; + } + return false; +} + +int hopcroft(int l) { + int ans = 0; + while (bfs(l)) for (int u = 0; u < l; u++) + if (matchl[u] == -1 && dfs(u)) { ans++; } + return ans; +} diff --git a/fontes/kmp.h b/fontes/kmp.h index e47fbce076a37dff55479d39be61893dcc48cfd5..43b41368ebf03cc3ed6ba90b715bf47d248365f4 100644 --- a/fontes/kmp.h +++ b/fontes/kmp.h @@ -1,25 +1,25 @@ vector<int> pre(string ne) { - int n = ne.size(); - vector<int> pi (n, 0); - for (int i = 1, j = 0; i < n; i++) { - while (j > 0 && ne[i] != ne[j]) { j = pi[j-1]; } - if (ne[i] == ne[j]) { j++; } - pi[i] = j; - } - return pi; + int n = ne.size(); + vector<int> pi (n, 0); + for (int i = 1, j = 0; i < n; i++) { + while (j > 0 && ne[i] != ne[j]) { j = pi[j-1]; } + if (ne[i] == ne[j]) { j++; } + pi[i] = j; + } + return pi; } int search(string hay, string ne) { - vector<int> pi = pre(ne); - int c = 0; - for (int i = 0, j = 0; i < hay.size(); i++) { - while (j > 0 && hay[i] != ne[j]) { j = pi[j-1]; } - if (hay[i] == ne[j]) { j++; } - if (j == ne.size()) { - c++; - // match at (i-j+1) - j = pi[j-1]; - } + vector<int> pi = pre(ne); + int c = 0; + for (int i = 0, j = 0; i < hay.size(); i++) { + while (j > 0 && hay[i] != ne[j]) { j = pi[j-1]; } + if (hay[i] == ne[j]) { j++; } + if (j == ne.size()) { + c++; + // match at (i-j+1) + j = pi[j-1]; } - return c; + } + return c; } diff --git a/fontes/kosaraju.cpp b/fontes/kosaraju.cpp deleted file mode 100644 index c23654f69aef8a803e95e7a4368e3052e2bd260d..0000000000000000000000000000000000000000 --- a/fontes/kosaraju.cpp +++ /dev/null @@ -1,41 +0,0 @@ -int timestamp = 0; -vector<int> visited (N); -vector<vector<int>> G (N); -vector<vector<int>> G_t (N); -vector<int> rep (N); -stack<int> S; - -void fill_stack (int u) { - visited[u] = timestamp; - for (int v : G[u]) if (visited[v] != timestamp) { - fill_stack(v); - } - S.push(u); -} - -void mark_component (int u, int my_rep) { - visited[u] = timestamp; - rep[u] = my_rep; - for (int v : G_t[u]) if (visited[v] != timestamp) { - mark_component(v, my_rep); - } -} - -vector<int> kosaraju (int n) { - timestamp++; - for (int u = 0; u < n; u++) if (visited[u] != timestamp) { - fill_stack(u); - } - - timestamp++; - vector<int> topo_components; - while (!S.empty()) { - int u = S.top(); S.pop(); - if (visited[u] != timestamp) { - mark_component(u, u); - topo_components.push_back(u); - } - } - - return topo_components; -} diff --git a/fontes/kosaraju.h b/fontes/kosaraju.h new file mode 100644 index 0000000000000000000000000000000000000000..6ca7baa46fff70760f555cb702a22d554a81f2b4 --- /dev/null +++ b/fontes/kosaraju.h @@ -0,0 +1,28 @@ +int cts = 1; +vector<int> vis (N), rep (N); +stack<int> sinks; + +void fill_stack(int u) { + if (vis[u] == cts) { return; } + vis[u] = cts; + for (int v : g_t[u]) { fill_stack(v); } + sinks.push(u); +} + +void mark_component(int u, int r) { + if (vis[u] == cts) { return; } + vis[u] = cts; rep[u] = r; + for (int v : g[u]) { mark_component(v, r); } +} + +stack<int> kosaraju(int n) { + for (int u = 0; u < n; u++) { fill_stack(u); } + cts++; + stack<int> topo; + while (!sinks.empty()) { + int u = sinks.top(); sinks.pop(); + mark_component(u, u); + if (rep[u] == u) topo.push(u); + } + return topo; +} diff --git a/fontes/kuhn.h b/fontes/kuhn.h new file mode 100644 index 0000000000000000000000000000000000000000..07e43a93cf9c28694d10adef89d4a2ba43b2423e --- /dev/null +++ b/fontes/kuhn.h @@ -0,0 +1,19 @@ +// u e v são enumerações distintas (podem repetir) +vector<vector<int>> g (L); +vector<int> matchr (R, -1); + +int dfs(int u) { + if (vis[u] == cts) { return 0; } + vis[u] = cts; + for (int v : g[u]) + if (matchr[v] == -1 || dfs(matchr[v])) { + matchr[v] = u; return 1; + } + return 0; +} + +int kuhn(int l) { + int ans = 0; + for (int u = 0; u < l; u++) { ans += dfs(u); cts++; } + return ans; +} diff --git a/fontes/linearsieve.h b/fontes/linearsieve.h new file mode 100644 index 0000000000000000000000000000000000000000..0f69a1d399c6869a10f660ac620e3af8583a2f7d --- /dev/null +++ b/fontes/linearsieve.h @@ -0,0 +1,9 @@ +vector<int> pr, lp (1e7+15); +void eulersieve(int n) { + for (int i = 2; i <= n; i++) { + if (lp[i] == 0) { lp[i] = i; pr.push_back(i); } + for (int j = 0; j < int(pr.size()) + && pr[j] <= lp[i] && i*pr[j] <= n; j++) + lp[i * pr[j]] = pr[j]; + } +} diff --git a/fontes/max-flow-ffek.cpp b/fontes/max-flow-ffek.cpp deleted file mode 100644 index a7ebd9528626c34d074d8919e67b791b231ccb76..0000000000000000000000000000000000000000 --- a/fontes/max-flow-ffek.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Minimum-cost, maximum flow, all costs 1 -// Ford-Fulkerson, Edmonds-Karp implementation -// Time: O(V^2 * E) - -vector<vector<int>> res (3e3+15); -vector<vector<int>> cap (3e3+15, vector<int>(3e3+15)); - -vector<int> parent(3e3+15); -vector<int> dist(3e3+15); - -bool bfs(int s, int t) { - fill(dist.begin(), dist.end(), oo); - dist[s] = 0; - - queue<int> Q; - Q.push(s); - - while (!Q.empty()) { - int u = Q.front(); Q.pop(); - if (u == t) { break; } - for (int v : res[u]) { - if (dist[v] != oo) { continue; } - if (cap[u][v] == 0) { continue; } - dist[v] = dist[u] + 1; - parent[v] = u; - Q.push(v); - } - } - - return dist[t] < oo; -} - -int ffek(int s, int t) { - int min_cost = 0; - int max_flow = 0; - while (bfs(s, t)) { - int flow = oo; - for (int u = t; u != s; u = parent[u]) { - flow = min(flow, cap[parent[u]][u]); - } - for (int u = t; u != s; u = parent[u]) { - cap[parent[u]][u] -= flow; - cap[u][parent[u]] += flow; - } - min_cost += flow * dist[t]; - max_flow += flow; - } - return max_flow; -} diff --git a/fontes/min-cost-max-flow.cpp b/fontes/min-cost-max-flow.cpp deleted file mode 100644 index 04f4304ddd2aa9efcb09e85f386dbf83d65bdf4d..0000000000000000000000000000000000000000 --- a/fontes/min-cost-max-flow.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Minimum-cost, maximum flow, variable cost -// Ford-Fulkerson, Edmonds-Karp implementation -// Time: O(V^2 * E) - -struct edge { int u, v, cap, cost; }; -vector<edge> edges; -vector<vector<int>> res (3e3+15); - -vector<bool> queued(3e3+15); -vector<int> parent(3e3+15); -vector<int> ind(3e3+15); -vector<int> dist(3e3+15); - -void link(int u, int v, int cap, int cost) { - res[u].push_back(edges.size()); - edges.push_back({ u, v, cap, cost }); - res[v].push_back(edges.size()); - edges.push_back({ v, u, 0, -cost }); -} - -bool spfa(int s, int t) { - fill(dist.begin(), dist.end(), oo); - fill(queued.begin(), queued.end(), false); - dist[s] = 0; - - queue<int> Q; - Q.push(s); - - while (!Q.empty()) { - int u = Q.front(); Q.pop(); - if (u == t) { break; } - queued[u] = false; - - for (int i : res[u]) { - edge e = edges[i]; - int v = e.v; - if (e.cap && dist[v] > dist[u] + e.cost) { - dist[v] = dist[u] + e.cost; - parent[v] = u; - ind[v] = i; - if (!queued[v]) { - Q.push(v); - queued[v] = true; - } - } - } - } - - return dist[t] < oo; -} - -pair<int, int> ffek(int s, int t) { - int min_cost = 0; - int max_flow = 0; - while (spfa(s, t)) { - int flow = oo; - for (int u = t; u != s; u = parent[u]) { - flow = min(flow, edges[ind[u]].cap); - } - for (int u = t; u != s; u = parent[u]) { - edges[ind[u] ].cap -= flow; - edges[ind[u]^1].cap += flow; - } - min_cost += flow * dist[t]; - max_flow += flow; - } - return {min_cost, max_flow}; -} diff --git a/fontes/numbers.h b/fontes/numbers.h index 0f4558ad979740b4aa5436df08047e510933493b..7dc33543514394535fc02d57fbd26dbe4b763f45 100644 --- a/fontes/numbers.h +++ b/fontes/numbers.h @@ -6,3 +6,4 @@ ll equals_zero_mod_m_inclusive(ll a, ll b, ll m) { ll multiples_inclusive(ll a, ll b, ll x) { return b/x - (a-1)/x; } ll ceil_div(ll x, ll y) { return (x/y) + bool(x%y); } +ll round_div(ll x, ll y) { return (x+y/2)/y; } diff --git a/fontes/point.h b/fontes/point.h index 822a380c0005b5d9c0fbe22559989377f623dc20..968b9802ba7f587ce3b1e92c3513ed7a185bd75a 100644 --- a/fontes/point.h +++ b/fontes/point.h @@ -7,10 +7,13 @@ pt vec(pt a, pt b) { return b - a; } int sgn(double v) { return (v > -EPS) - (v < EPS); } // -1 (cw), 0 (colinear), +1 (ccw) int seg_ornt(pt a, pt b, pt c) { - return sgn(cross(vec(a, b), vec(a, c))); } + return sgn(cross(vec(a, b), vec(a, c))); +} int ccw(pt a, pt b, pt c, bool col) { - int o = seg_ornt(a, b, c); - return (o == 1) || (o == 0 && col); } + int o = seg_ornt(a, b, c); + return (o == 1) || (o == 0 && col); +} const double PI = acos(-1); double angle(pt a, pt b, pt c) { - return abs(remainder(arg(a-b) - arg(c-b), 2.0 * PI)); } + return abs(remainder(arg(a-b) - arg(c-b), 2.0 * PI)); +} diff --git a/fontes/prim.h b/fontes/prim.h index 666a8f4ebce89e0176e7c23765d01b415d0209fe..7c8431a28340e7315f6ff3cc300878c0dc514f52 100644 --- a/fontes/prim.h +++ b/fontes/prim.h @@ -2,6 +2,7 @@ vector<bool> vis (N); vector<int> par (N, -1); vector<ll> d (N, oo); vector<vector<ii>> pt (N); + ll prim(int src) { ll sum = 0; priority_queue<ii, vector<ii>, greater<ii>> Q; diff --git a/fontes/rabinkarp.h b/fontes/rabinkarp.h index c725ee9349429ec2f71850775d66c04c2184af83..f6ed7f74c75439e0dd3182305ca0b95981ccb8bf 100644 --- a/fontes/rabinkarp.h +++ b/fontes/rabinkarp.h @@ -1,20 +1,20 @@ const int P = 31; const int M = 1e9 + 9; int search(string hay, string ne) { - int n = hay.size(), m = ne.size(); - vector<ll> ps (max(n, m), 1); - for (int i = 1; i < max(n, m); i++) - ps[i] = (ps[i-1] * P) % M; - vector<ll> h (n+1, 0); - for (int i = 0; i < n; i++) - h[i+1] = (h[i] + (hay[i]-'a'+1) * ps[i]) % M; - ll hne = 0; - for (int i = 0; i < m; i++) - hne = (hne + (ne[i]-'a'+1) * ps[i]) % M; - int c = 0; - for (int i = 0; i < n - m + 1; i++) - if ((h[i+m] - h[i] + M) % M == hne * ps[i] % M) { - // match at i - c++; - } - return c; + int n = hay.size(), m = ne.size(); + vector<ll> ps (max(n, m), 1); + for (int i = 1; i < max(n, m); i++) + ps[i] = (ps[i-1] * P) % M; + vector<ll> h (n+1, 0); + for (int i = 0; i < n; i++) + h[i+1] = (h[i] + (hay[i]-'a'+1) * ps[i]) % M; + ll hne = 0; + for (int i = 0; i < m; i++) + hne = (hne + (ne[i]-'a'+1) * ps[i]) % M; + int c = 0; + for (int i = 0; i < n - m + 1; i++) + if ((h[i+m] - h[i] + M) % M == hne * ps[i] % M) { + // match at i + c++; + } + return c; } diff --git a/fontes/sieve-of-eratosthenes.cpp b/fontes/sieve-of-eratosthenes.cpp deleted file mode 100644 index 727f6e30dcbceb629fb486e4cdeca42d681cf541..0000000000000000000000000000000000000000 --- a/fontes/sieve-of-eratosthenes.cpp +++ /dev/null @@ -1,58 +0,0 @@ -vector<bool> sieve (n + 1, true); - -void sieve_eratosthenes /* O (n lg lg n) */ (int n) { - for (int i = 2; i * i <= n; i++) if (sieve[i]) { - for (int j = i * i; j <= n; j += i) { - sieve[j] = false; - } - } -} - -vector<int> divisors (n + 1); - -void number_of_divisors /* O(n lg n) */ (int n) { - for (int i = 1; i <= n; ++i) - for (int j = i; j <= n; j += i) - divisors[j]++; -} - -vector<int> sum_divisors (n + 1); - -void sum_of_divisors /* O(n lg n) */ (int n) { - for (int i = 1; i <= n; ++i) - for (int j = i; j <= n; j += i) - sum_divisors[j] += i; -} - -vector<int> totient (n + 1); - -void euler_totient /* O(n lg lg n) */ (int n) { - for (int i = 1; i <= n; ++i) totient[i] = i; - for (int i = 2; i <= n; ++i) - if (totient[i] == i) - for (int j = i; j <= n; j += i) - totient[j] -= totient[j] / i; -} - -vector<int> big (n + 1) = { 1, 1 }; - -void biggest_prime_divisor /* O(n lg lg n) */ (int n) { - for (int i = 1; i <= n; ++i) - if (big[i] == 1) - for (int j = i; j <= n; j += i) - big[j] = i; -} - -vector<int> lp (n + 1); -vector<int> pr; - -void linear_sieve /* O(n) */ (int n) { - for (int i = 2; i <= n; i++) { - if (lp[i] == 0) { - lp[i] = i; - pr.push_back(i); - } - for (int j = 0; j < pr.size() && pr[j] <= lp[i] && i * pr[j] <= n; j++) - lp[i * pr[j]] = pr[j]; - } -} diff --git a/fontes/sieve.h b/fontes/sieve.h new file mode 100644 index 0000000000000000000000000000000000000000..470673b47ec958c0ac5d1d74ddbbca65349cfced --- /dev/null +++ b/fontes/sieve.h @@ -0,0 +1,6 @@ +vector<bool> sieve (1e7+15, true); +void eratosthenes(int n) { + for (int i = 2; i * i <= n; i++) if (sieve[i]) + for (int j = i * i; j <= n; j += i) + sieve[j] = false; +} diff --git a/fontes/spfa.h b/fontes/spfa.h new file mode 100644 index 0000000000000000000000000000000000000000..6baf3c7f793b79fed74810f709f84bf2e470cce6 --- /dev/null +++ b/fontes/spfa.h @@ -0,0 +1,27 @@ +vector<ll> d (N); vector<bool> queu (N); +vector<int> cnt (N); + +bool spfa(int src, int n) { + fill(d.begin(), d.end(), oo); + fill(cnt.begin(), cnt.end(), 0); + d[src] = 0; + queue<int> q; q.push(src); + while (!q.empty()) { + int u = q.front(); q.pop(); + queu[u] = 0; + for (auto [v, w] : g[u]) { + if (d[v] > d[u] + w) { + d[v] = d[u] + w; + if (!queu[v]) { + q.push(v); + queu[v] = 1; + cnt[v]++; + if (cnt[v] > n) + // negative cycle + return false; + } + } + } + } + return true; +} diff --git a/fontes/stress.sh b/fontes/stress.sh index 39e076b036f382ad938e3319a9cd9c7bc9b5ab70..8e01a861828e73071cff997380f073ba3c581b27 100644 --- a/fontes/stress.sh +++ b/fontes/stress.sh @@ -2,8 +2,7 @@ for (( I=0; I < 5; I++ )); do ./gen $I >a.in ./brute <a.in >a.exp ./a.out <a.in >a.out - diff -u a.exp a.out - if [[ $? -ne 0 ]]; then + if diff -u a.exp a.out; then : ; else echo "--> entrada:"; cat a.in echo "--> saída esperada"; cat a.exp echo "--> saída obtida"; cat a.out diff --git a/fontes/sumdivsieve.h b/fontes/sumdivsieve.h new file mode 100644 index 0000000000000000000000000000000000000000..afd4fa6801650873e8b9160994f97906eb36e529 --- /dev/null +++ b/fontes/sumdivsieve.h @@ -0,0 +1,7 @@ +vector<int> sumdiv (N); + +void sum_of_divisors(int n) { + for (int i = 1; i <= n; ++i) + for (int j = i; j <= n; j += i) + sumdiv[j] += i; +} diff --git a/fontes/tarjan.cpp b/fontes/tarjan.cpp deleted file mode 100644 index 7dfb4680344c63e50b0cae2199cffd5862e608fc..0000000000000000000000000000000000000000 --- a/fontes/tarjan.cpp +++ /dev/null @@ -1,43 +0,0 @@ -int timestamp = 0; -vector<int> id (1e5 + 1); -vector<int> lowlink (1e5 + 1, oo); -vector<int> rep (1e5 + 1, 0); -vector<int> visited (1e5 + 1, 0); -vector<bool> on_stack (1e5 + 1, false); -stack<int> topo_components; -stack<int> S; - -int next_id = 0; - -void tarjan_dfs (int u) { - if (visited[u] == timestamp) { return; } - visited[u] = timestamp; - S.push(u); on_stack[u] = true; - id[u] = lowlink[u] = next_id++; - - for (int v : G[u]) { - tarjan_dfs(v); - if (on_stack[v]) { - lowlink[u] = min(lowlink[u], lowlink[v]); - } - } - - if (id[u] == lowlink[u]) { - int v; - do { - v = S.top(); S.pop(); - on_stack[v] = false; - lowlink[v] = id[u]; - rep[v] = u; - } while (v != u); - topo_components.push(u); - } -} - -stack<int> tarjan (int n) { - timestamp++; - for (int i = 0; i < n; i++) { - tarjan_dfs(i); - } - return topo_components; -} diff --git a/fontes/tarjan.h b/fontes/tarjan.h index 8a16e74bc7087a7d65f650c7a0b8f6db6034eddb..93f6c4cf2be909fc30cd68438a6081610d5d75e4 100644 --- a/fontes/tarjan.h +++ b/fontes/tarjan.h @@ -1,20 +1,25 @@ vector<int> tin (N, -1), lowlnk (N, -1), rep (N); -stack<int> st; +stack<int> st, topo; +int cts = 0; + void dfs_tarjan(int u) { - if (tin[u] != -1) { return; } - lowlnk[u] = tin[u] = vis[u] = cts++; - st.push(u); - for (int v : g[u]) { - dfs_tarjan(v); - if (vis[v]) lowlnk[u] = min(lowlnk[u], lowlnk[v]); - } - if (lowlnk[u] == tin[u]) { - int v; do { - v = st.top(); st.pop(); vis[v] = 0; - rep[v] = u; - } while (u != v); - } + if (tin[u] != -1) { return; } + lowlnk[u] = tin[u] = vis[u] = cts++; + st.push(u); + for (int v : g[u]) { + dfs_tarjan(v); + if (vis[v]) lowlnk[u] = min(lowlnk[u], lowlnk[v]); + } + if (lowlnk[u] == tin[u]) { + int v; do { + v = st.top(); st.pop(); vis[v] = 0; + rep[v] = u; + } while (u != v); + topo.push(u); + } } -void tarjan(int n) { - for (int u = 0; u < n; u++) { dfs_tarjan(u); } + +stack<int> tarjan(int n) { + for (int u = 0; u < n; u++) { dfs_tarjan(u); } + return topo; } diff --git a/fontes/topo.h b/fontes/topo.h index e3b991201700a343716b01f280bd29d224ddca2b..0a3530e395c2117fd3fd7dd72be8344050506708 100644 --- a/fontes/topo.h +++ b/fontes/topo.h @@ -1,10 +1,12 @@ vector<bool> vis (N); stack<int> st; + void dfs_topo(int u) { if (vis[u]) { return; } vis[u] = 1; for (int v : g[u]) { dfs_topo(v); } st.push(u); } + vector<int> toposort(int n) { fill(visited.begin(), visited.begin() + n, false); vector<int> topo;