Skip to content

Commit

Permalink
Merge branch 'master' into reorganize_files
Browse files Browse the repository at this point in the history
  • Loading branch information
OmeletWithoutEgg committed Oct 7, 2023
2 parents ffdf0e3 + 8809d05 commit 0c29799
Show file tree
Hide file tree
Showing 15 changed files with 273 additions and 151 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
push:
branches: [ master ]
paths-ignore:
- 'docs/*'
- 'docs/**'
- 'pdf/codebook.pdf'
- 'README.md'
- '.editorconfig'
Expand Down
1 change: 1 addition & 0 deletions codes/Basic/debug.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define all(x) begin(x), end(x)
#ifdef CKISEKI
#define safe cerr<<__PRETTY_FUNCTION__<<" line "<<__LINE__<<" safe\n"
#define debug(a...) debug_(#a, a)
Expand Down
1 change: 1 addition & 0 deletions codes/Basic/vimrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ map <F8> <ESC>:w<CR>:!g++ "%" -o "%<" -g -std=gnu++20 -DCKISEKI -Wall -Wextra -W
map <F9> <ESC>:w<CR>:!g++ "%" -o "%<" -O2 -g -std=gnu++20 && echo success<CR>
map <F10> <ESC>:!./"%<"<CR>
ca Hash w !cpp -dD -P -fpreprocessed \| tr -d '[:space:]' \| md5sum \| cut -c-6
let c_no_curly_error=1
" setxkbmap -option caps:ctrl_modifier
80 changes: 37 additions & 43 deletions codes/FlowAndMatching/Dinic.cpp
Original file line number Diff line number Diff line change
@@ -1,46 +1,40 @@
template <typename Cap = int64_t> class Dinic {
private:
struct E { int to, rev; Cap cap; }; int n, st, ed;
vector<vector<E>> G; vector<int> lv, idx;
bool BFS() {
lv.assign(n, -1);
queue<int> bfs; bfs.push(st); lv[st] = 0;
while (not bfs.empty()) {
int u = bfs.front(); bfs.pop();
for (auto e: G[u]) {
if (e.cap <= 0 or lv[e.to] != -1) continue;
bfs.push(e.to); lv[e.to] = lv[u] + 1;
}
}
return lv[ed] != -1;
}
Cap DFS(int u, Cap f) {
if (u == ed) return f;
Cap ret = 0;
for(int &i = idx[u]; i < int(G[u].size()); ++i) {
auto &e = G[u][i];
if (e.cap <= 0 or lv[e.to] != lv[u]+1) continue;
Cap nf = DFS(e.to, min(f, e.cap));
ret += nf; e.cap -= nf; f -= nf;
G[e.to][e.rev].cap += nf;
if (f == 0) return ret;
}
if (ret == 0) lv[u] = -1;
return ret;
}
struct E { int to, rev; Cap cap; }; int n, st, ed;
vector<vector<E>> G; vector<size_t> lv, idx;
bool BFS() {
lv.assign(n, 0); idx.assign(n, 0);
queue<int> bfs; bfs.push(st); lv[st] = 1;
while (not bfs.empty()) {
int u = bfs.front(); bfs.pop();
for (auto e: G[u]) if (e.cap > 0 and !lv[e.to])
bfs.push(e.to), lv[e.to] = lv[u] + 1;
}
return lv[ed];
}
Cap DFS(int u, Cap f = numeric_limits<Cap>::max()) {
if (u == ed) return f;
Cap ret = 0;
for (auto &i = idx[u]; i < G[u].size(); ++i) {
auto &[to, rev, cap] = G[u][i];
if (cap <= 0 or lv[to] != lv[u] + 1) continue;
Cap nf = DFS(to, min(f, cap));
ret += nf; cap -= nf; f -= nf;
G[to][rev].cap += nf;
if (f == 0) return ret;
}
if (ret == 0) lv[u] = 0;
return ret;
}
public:
void init(int n_) { G.assign(n = n_, vector<E>()); }
void add_edge(int u, int v, Cap c) {
G[u].push_back({v, int(G[v].size()), c});
G[v].push_back({u, int(G[u].size())-1, 0});
}
Cap max_flow(int st_, int ed_) {
st = st_, ed = ed_; Cap ret = 0, f;
while (BFS()) {
idx.assign(n, 0);
f = DFS(st, numeric_limits<Cap>::max()); ret += f;
if (f == 0) break;
}
return ret;
}
};
void init(int n_) { G.assign(n = n_, vector<E>()); }
void add_edge(int u, int v, Cap c) {
G[u].push_back({v, int(G[v].size()), c});
G[v].push_back({u, int(G[u].size())-1, 0});
}
Cap max_flow(int st_, int ed_) {
st = st_, ed = ed_; Cap ret = 0;
while (BFS()) ret += DFS(st);
return ret;
}
}; // test @ luogu P3376
30 changes: 22 additions & 8 deletions codes/FlowAndMatching/FlowModels.tex
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@
\item Connect $v \to v^\prime$ with weight $2\mu(v)$, where $\mu(v)$ is the cost of the cheapest edge incident to $v$.
\item Find the minimum weight perfect matching on $G^\prime$.
\end{enumerate}
\item Project selection problem
\vspace{-1em}
\begin{enumerate}
\itemsep-0.3em
\item If $p_v > 0$, create edge $(s, v)$ with capacity $p_v$; otherwise, create edge $(v, t)$ with capacity $-p_v$.
\item Create edge $(u, v)$ with capacity $w$ with $w$ being the cost of choosing $u$ without choosing $v$.
\item The mincut is equivalent to the maximum profit of a subset of projects.
\end{enumerate}
%\item Project selection problem
%\vspace{-1em}
%\begin{enumerate}
%\itemsep-0.3em
%\item If $p_v > 0$, create edge $(s, v)$ with capacity $p_v$; otherwise, create edge $(v, t)$ with capacity $-p_v$.
%\item Create edge $(u, v)$ with capacity $w$ with $w$ being the cost of choosing $u$ without choosing $v$.
%\item The mincut is equivalent to the maximum profit of a subset of projects.
%\end{enumerate}
% \item 0/1 quadratic programming
% \vspace{-0.5em}
% \[ \sum_x{c_xx} + \sum_y{c_y\bar{y}} + \sum_{xy}c_{xy}x\bar{y} + \sum_{xyx^\prime y^\prime}c_{xyx^\prime y^\prime}(x\bar{y} + x^\prime\bar{y^\prime}) \]
Expand All @@ -74,4 +74,18 @@
% \item Create edge $(x, y)$ with capacity $c_{xy}$.
% \item Create edge $(x, y)$ and edge $(x^\prime, y^\prime)$ with capacity $c_{xyx^\prime y^\prime}$.
% \end{enumerate}
\item Submodular functions minimization
\vspace{-1em}
\begin{itemize}
\item For a function $f: 2^V \to \mathbb{R}$, $f$ is a submodular function iff
\begin{itemize}
\item $\forall S,T \subseteq V$, $f(S) + f(T) \geq f(S \cup T) + f(S \cap T)$, or
\item $\forall X \subseteq Y \subseteq V$, $x\notin Y$, $f(X\cup\{x\})-f(X)\geq f(Y\cup\{x\})-f(Y)$.
\end{itemize}
\item To minimize $\sum_i \theta_i (x_i) + \sum_{i< j} \phi_{ij} (x_i, x_j) + \sum_{i< j< k} \psi_{ijk} (x_i, x_j, x_k)$
\item If $\theta_i(1)\geq\theta_i(0)$, add edge ($S$, $i$, $\theta_i(1)-\theta_i(0)$) and $\theta_i(0)$ to answer; otherwise, ($i$, $T$, $\theta_i(0)-\theta_i(1)$) and $\theta_i(1)$.
\item Add edges ($i$, $j$, $\phi_{ij}(0,1)+\phi_{ij}(1,0)-\phi_{ij}(0,0)-\phi_{ij}(1,1)$).
\item Denote $x_{ijk}$ as helper nodes. Let $P=\psi_{ijk}(0,0,0)+\psi_{ijk}(0,1,1)+\psi_{ijk}(1,0,1)+\psi_{ijk}(1,1,0)-\psi_{ijk}(0,0,1)-\psi_{ijk}(0,1,0)-\psi_{ijk}(1,0,0)-\psi_{ijk}(1,1,1)$. Add $-P$ to answer. If $P \geq 0$, add edges ($i$, $x_{ijk}$, $P$), ($j$,$x_{ijk}$,$P$), ($k$,$x_{ijk}$,$P$), ($x_{ijk}$, $T$, $P$); otherwise ($x_{ijk}$,$i$,$-P$), ($x_{ijk}$,$j$,$-P$), ($x_{ijk}$,$k$,$-P$), ($S$, $x_{ijk}$, $-P$).
\item The minimum cut of this graph will be the the minimum value of the function above.
\end{itemize}
\end{itemize}
109 changes: 60 additions & 49 deletions codes/FlowAndMatching/MinCostCirculation.cpp
Original file line number Diff line number Diff line change
@@ -1,52 +1,63 @@
struct Edge { int to, cap, rev, cost; };
vector<Edge> g[kN];
int dist[kN], pv[kN], ed[kN];
bool mark[kN];
int NegativeCycle(int n) {
memset(mark, false, sizeof(mark));
memset(dist, 0, sizeof(dist));
int upd = -1;
for (int i = 0; i <= n; ++i) {
for (int j = 0; j < n; ++j) {
int idx = 0;
for (auto &e : g[j]) {
if(e.cap > 0 && dist[e.to] > dist[j] + e.cost){
dist[e.to] = dist[j] + e.cost;
pv[e.to] = j, ed[e.to] = idx;
if (i == n) {
upd = j;
while(!mark[upd])mark[upd]=1,upd=pv[upd];
return upd;
}
}
idx++;
}
}
}
return -1;
int vis[N], visc, fa[N], fae[N], head[N], mlc = 1;
struct ep {
int to, next;
ll flow, cost;
} e[M << 1];
void adde(int u, int v, ll fl, int cs) {
e[++mlc] = {v, head[u], fl, cs};
head[u] = mlc;
e[++mlc] = {u, head[v], 0, -cs};
head[v] = mlc;
}
void dfs(int u) {
vis[u] = 1;
for (int i = head[u], v; i; i = e[i].next)
if (!vis[v = e[i].to] and e[i].flow)
fa[v] = u, fae[v] = i, dfs(v);
}
int Solve(int n) {
int rt = -1, ans = 0;
while ((rt = NegativeCycle(n)) >= 0) {
memset(mark, false, sizeof(mark));
vector<pair<int, int>> cyc;
while (!mark[rt]) {
cyc.emplace_back(pv[rt], ed[rt]);
mark[rt] = true;
rt = pv[rt];
}
reverse(cyc.begin(), cyc.end());
int cap = kInf;
for (auto &i : cyc) {
auto &e = g[i.first][i.second];
cap = min(cap, e.cap);
}
for (auto &i : cyc) {
auto &e = g[i.first][i.second];
e.cap -= cap;
g[e.to][e.rev].cap += cap;
ans += e.cost * cap;
}
ll phi(int x) {
static ll pi[N];
if (x == -1) return 0;
if (vis[x] == visc) return pi[x];
return vis[x] = visc, pi[x] = phi(fa[x]) - e[fae[x]].cost;
}
void pushflow(int x, ll &cost) {
int v = e[x ^ 1].to, u = e[x].to;
++visc;
while (v != -1) vis[v] = visc, v = fa[v];
while (u != -1 && vis[u] != visc)
vis[u] = visc, u = fa[u];
vector<int> cyc;
int e2 = 0, pa = 2;
ll f = e[x].flow;
for (int i = e[x ^ 1].to; i != u; i = fa[i]) {
cyc.push_back(fae[i]);
if (e[fae[i]].flow < f)
f = e[fae[e2 = i] ^ (pa = 0)].flow;
}
for (int i = e[x].to; i != u; i = fa[i]) {
cyc.push_back(fae[i] ^ 1);
if (e[fae[i] ^ 1].flow < f)
f = e[fae[e2 = i] ^ (pa = 1)].flow;
}
return ans;
cyc.push_back(x);
for (int cyc_i : cyc) {
e[cyc_i].flow -= f, e[cyc_i ^ 1].flow += f;
cost += 1ll * f * e[cyc_i].cost;
}
if (pa == 2) return;
int le = x ^ pa, l = e[le].to, o = e[le ^ 1].to;
while (l != e2) {
vis[o] = 0;
swap(le ^= 1, fae[o]), swap(l, fa[o]), swap(l, o);
}
}
ll simplex() { // 1-based
ll cost = 0;
memset(fa, -1, sizeof(fa)), dfs(1);
vis[1] = visc = 2, fa[1] = -1;
for (int i = 2, pre = -1; i != pre; i = (i == mlc ? 2 : i + 1))
if (e[i].flow and e[i].cost < phi(e[i ^ 1].to) - phi(e[i].to))
pushflow(pre = i, cost);
return cost;
}
18 changes: 9 additions & 9 deletions codes/Geometry/Circle/MinCircleCover.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
// be careful of type
Cir getCircum(P a, P b, P c){
Cir getCircum(P a, P b, P c){ // P = complex<llf>
P z1 = a - b, z2 = a - c; llf D = cross(z1, z2) * 2;
llf c1 = dot(a + b, z1), c2 = dot(a + c, z2);
P o = (c2 * conj(z1) - c1 * conj(z2)) / D;
P o = rot90(c2 * z1 - c1 * z2) / D;
return { o, abs(o - a) };
}
Cir minCircleCover(vector<P> &pts) {
shuffle(pts.begin(), pts.end(), mt19937(114514));
Cir c = { pts[0], 0 };
for(int i = 0; i < (int)pts.size(); i++) {
assert (!pts.empty());
ranges::shuffle(pts, mt19937(114514));
Cir c = { 0, 0 };
for(size_t i = 0; i < pts.size(); i++) {
if (dist(pts[i], c.o) <= c.r) continue;
c = { pts[i], 0 };
for (int j = 0; j < i; j++) {
for (size_t j = 0; j < i; j++) {
if (dist(pts[j], c.o) <= c.r) continue;
c.o = (pts[i] + pts[j]) / llf(2);
c.r = dist(pts[i], c.o);
for (int k = 0; k < j; k++) {
for (size_t k = 0; k < j; k++) {
if (dist(pts[k], c.o) <= c.r) continue;
c = getCircum(pts[i], pts[j], pts[k]);
}
}
}
return c;
}
} // test @ TIOJ 1093 & luogu P1742
25 changes: 11 additions & 14 deletions codes/Geometry/MinMaxEnclosingRect.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
// from 8BQube, plz ensure p is strict convex hull
const llf INF = 1e18, qi = acos(-1) / 2 * 3;
pair<llf, llf> solve(vector<P> &p) {
#define Z(v) (p[v] - p[i])
llf mx = 0, mn = INF;
int n = (int)p.size(); p.emplace_back(p[0]);
pair<llf, llf> solve(const vector<P> &p) {
llf mx = 0, mn = INF; int n = (int)p.size();
for (int i = 0, u = 1, r = 1, l = 1; i < n; ++i) {
#define Z(v) (p[(v) % n] - p[i])
P e = Z(i + 1);
while (cross(e, Z(u + 1)) > cross(e, Z(u)))
u = (u + 1) % n;
while (dot(e, Z(r + 1)) > dot(e, Z(r)))
r = (r + 1) % n;
if (!i) l = (r + 1) % n;
while (dot(e, Z(l + 1)) < dot(e, Z(l)))
l = (l + 1) % n;
P D = p[r] - p[l];
mn = min(mn, dot(e, D) / llf(norm(e)) * cross(e, Z(u)));
while (cross(e, Z(u + 1)) > cross(e, Z(u))) ++u;
while (dot(e, Z(r + 1)) > dot(e, Z(r))) ++r;
if (!i) l = r + 1;
while (dot(e, Z(l + 1)) < dot(e, Z(l))) ++l;
P D = p[r % n] - p[l % n];
llf H = cross(e, Z(u)) / llf(norm(e));
mn = min(mn, dot(e, D) * H);
llf B = sqrt(norm(D)) * sqrt(norm(Z(u)));
llf deg = (qi - acos(dot(D, Z(u)) / B)) / 2;
mx = max(mx, B * sin(deg) * sin(deg));
}
return {mn, mx};
}
} // test @ UVA 819
24 changes: 12 additions & 12 deletions codes/Geometry/MinkowskiSum.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// A, B are convex hull rotate to min by (X, Y)
// A, B are strict convex hull rotate to min by (X, Y)
vector<P> Minkowski(vector<P> A, vector<P> B) {
vector<P> C(1, A[0] + B[0]), s1, s2;
const int N = (int)A.size(), M = (int)B.size();
for(int i = 0; i < N; ++i)
s1.pb(A[(i + 1) % N] - A[i]);
for(int i = 0; i < M; i++)
s2.pb(B[(i + 1) % M] - B[i]);
for(int i = 0, j = 0; i < N || j < M;)
if (j >= N || (i < M && cross(s1[i], s2[j]) >= 0))
C.pb(C.back() + s1[i++]);
else
C.pb(C.back() + s2[j++]);
return hull(C), C;
vector<P> sa(N), sb(M), C(N + M + 1);
for (int i = 0; i < N; i++) sa[i] = A[(i+1)%N]-A[i];
for (int i = 0; i < M; i++) sb[i] = B[(i+1)%M]-B[i];
C[0] = A[0] + B[0];
for (int i = 0, j = 0; i < N || j < M; ) {
P e = (j>=M || (i<N && cross(sa[i], sb[j])>=0))
? sa[i++] : sb[j++];
C[i + j] = e;
}
partial_sum(all(C), C.begin()); C.pop_back();
return convex_hull(C); // just to remove colinear
}
2 changes: 1 addition & 1 deletion codes/Misc/PrefixSubstringLCS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ void all_lcs(string S, string T) { // 0-base
// here, LCS(s[0, a], t[b, c]) =
// c - b + 1 - sum([h[i] > b] | i <= c)
}
}
} // test @ yosupo judge
16 changes: 16 additions & 0 deletions codes/String/LyndonFactorization.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// partition s = w[0] + w[1] + ... + w[k-1],
// w[0] >= w[1] >= ... >= w[k-1]
// each w[i] strictly smaller than all its suffix
void duval(const auto &s, auto &&report) {
int n = (int)s.size(), i = 0, j, k;
while (i < n) {
for (j = i + 1, k = i; j < n && s[k] <= s[j]; j++)
k = (s[k] < s[j] ? i : k + 1);
// if (i < n / 2 && j >= n / 2) {
// for min cyclic shift, call duval(s + s)
// then here s.substr(i, n / 2) is min cyclic shift
// }
for (; i <= k; i += j - k)
report(i, j - k); // s.substr(l, len)
}
} // tested @ luogu 6114, 1368 & UVA 719
Loading

0 comments on commit 0c29799

Please sign in to comment.