基本
文件头
| |
| |
| #include <bits/stdc++.h> |
| |
| using namespace std; |
| |
| using LL = long long; |
| using ULL = unsigned long long; |
| |
| #define F(i, l, r) for (int i = (l); i <= (r); ++i) |
| #define FF(i, r, l) for (int i = (r); i >= (l); --i) |
| #define MAX(a, b) ((a) = max((a), (b))) |
| #define MIN(a, b) ((a) = min((a), (b))) |
| #define SZ(a) ((int)((a).size()) - 1) |
| |
| signed main(void) |
| { |
| |
| |
| ios::sync_with_stdio(0), cin.tie(nullptr); |
| |
| return 0; |
| } |
fread/fwrite快读快写
| namespace IO |
| { |
| constexpr int BUF = 1000000; |
| |
| char ibuf[BUF]; |
| int ilen = 0, icur = 0; |
| |
| int rc(void) |
| { |
| if (icur == ilen) |
| { |
| icur = 0; |
| ilen = fread(ibuf, sizeof (char), BUF, stdin); |
| if (icur == ilen) return -1; |
| } |
| return ibuf[icur++]; |
| } |
| |
| LL rll(void) |
| { |
| LL x = 0, s = 1, c = rc(); |
| while (c < '0' || c > '9') |
| { |
| if (c == -1) return 0; |
| s = c == '-' ? -1 : 1; |
| c = rc(); |
| } |
| do { |
| x = (x << 1) + (x << 3) + c - '0'; |
| c = rc(); |
| } while (c >= '0' && c <= '9'); |
| return x * s; |
| } |
| |
| char obuf[BUF], ostk[20]; |
| int olen = 0, otop; |
| |
| void flush(void) |
| { |
| fwrite(obuf, sizeof (char), olen, stdout); |
| olen = 0; |
| } |
| |
| void wc(char c) |
| { |
| if (olen == BUF) flush(); |
| obuf[olen++] = c; |
| } |
| |
| void wll(LL x) |
| { |
| if (x == 0) return wc('0'); |
| if (x < 0) x = -x, wc('-'); |
| otop = 0; |
| while (x) ostk[++otop] = x % 10 + '0', x /= 10; |
| while (otop) wc(ostk[otop--]); |
| } |
| } |
自动对拍
| |
| |
| #include <bits/stdc++.h> |
| |
| using namespace std; |
| |
| using LL = long long; |
| using ULL = unsigned long long; |
| |
| #define F(i, l, r) for (int i = (l); i <= (r); ++i) |
| #define FF(i, r, l) for (int i = (r); i >= (l); --i) |
| #define MAX(a, b) ((a) = max(a, b)) |
| #define MIN(a, b) ((a) = min(a, b)) |
| #define SZ(a) ((int)((a).size()) - 1) |
| |
| const string NAME = "b"; |
| const string GEN = ".\\" + NAME + "_gen", STD = ".\\" + NAME + "_std", SOL = ".\\" + NAME; |
| const string DIFF = "fc.exe " + NAME + ".out " + NAME + ".ans"; |
| |
| signed main(void) |
| { |
| |
| |
| ios::sync_with_stdio(0), cin.tie(nullptr); |
| |
| int tc = 0; |
| while (1) |
| { |
| system(GEN.c_str()); |
| system(STD.c_str()); |
| LL c = -clock(); |
| system(SOL.c_str()); |
| c += clock(); |
| if (system(DIFF.c_str())) |
| { |
| cerr << "Wrong!\n"; |
| return 1; |
| } |
| cerr << "OK on test case #" << ++tc << ". Time: " << (double)c / CLOCKS_PER_SEC << "s.\n"; |
| } |
| |
| return 0; |
| } |
数据结构
并查集
| struct Dsu |
| { |
| int ff[N], sz[N]; |
| |
| void init(int nn) |
| { |
| iota(ff + 1, ff + nn + 1, 1); |
| fill(sz + 1, sz + nn + 1, 1); |
| } |
| |
| int getanc(int u) { return u == ff[u] ? u : (ff[u] = getanc(ff[u])); } |
| |
| bool merge(int u, int v) |
| { |
| u = getanc(u), v = getanc(v); |
| if (u == v) return 0; |
| if (sz[u] > sz[v]) swap(u, v); |
| ff[u] = v; |
| sz[v] += sz[u]; |
| return 1; |
| } |
| } dsu; |
多项式
拉格朗日插值
| LL inter(const vector<pair<LL, LL>> &pts, LL x) |
| { |
| LL ans = 0; |
| F(i, 0, SZ(pts)) |
| { |
| LL t = 1; |
| F(j, 0, SZ(pts)) if (j != i) |
| t = t * (pts[i].first - pts[j].first) % MOD; |
| t = kpow(t + MOD) * pts[i].second % MOD; |
| F(j, 0, SZ(pts)) if (j != i) |
| t = t * (x - pts[j].first) % MOD; |
| ans += t; |
| } |
| return (ans % MOD + MOD) % MOD; |
| } |
NTT
| namespace NTT |
| { |
| constexpr int NN = 1 << 21, P = 998244353, G = 114514; |
| |
| LL kpow(LL x, LL k = P - 2) |
| { |
| x = x % P; |
| LL r = 1; |
| while (k) |
| { |
| if (k & 1) r = r * x % P; |
| x = x * x % P; |
| k >>= 1; |
| } |
| return r; |
| } |
| |
| int nn, kk, rv[NN]; |
| |
| void init(int n) |
| { |
| nn = 1, kk = 0; |
| while (nn <= n) nn <<= 1, ++kk; |
| rv[0] = 0; |
| F(i, 1, nn - 1) rv[i] = rv[i >> 1] >> 1 | (i & 1) << kk - 1; |
| } |
| |
| void ntt(int *a, int n, int flg) |
| { |
| if (nn <= n || (nn >> 1) > n) init(n); |
| F(i, 0, nn - 1) if (rv[i] > i) swap(a[i], a[rv[i]]); |
| F(k, 0, kk - 1) |
| { |
| int l = 1 << k; |
| LL g = kpow(G, (P - 1) >> k + 1); |
| for (int i = 0; i < nn; i += l << 1) |
| { |
| LL cg = 1; |
| F(j, 0, l - 1) |
| { |
| LL x = a[i + j], y = a[i + j + l]; |
| a[i + j] = (x + cg * y) % P; |
| a[i + j + l] = (x - cg * y) % P; |
| cg = cg * g % P; |
| } |
| } |
| } |
| if (flg == -1) |
| { |
| reverse(a + 1, a + nn); |
| LL ivn = kpow(nn); |
| F(i, 0, nn - 1) a[i] = a[i] * ivn % P; |
| } |
| } |
| } |
字符串
SA
| namespace SA |
| { |
| int rk[N << 1], tmp[N], tot; |
| int pos[N]; |
| |
| void calc_sa(int *sa, string s) |
| { |
| int n = s.size() - 1; |
| F(i, 1, 127) pos[i] = 0; |
| F(i, 1, n) pos[s[i]] += 1; |
| F(i, 1, 127) pos[i] += pos[i - 1]; |
| FF(i, n, 1) sa[pos[s[i]]--] = i; |
| F(i, 1, n) |
| { |
| if (i != 1 && s[sa[i]] == s[sa[i - 1]]) |
| rk[sa[i]] = rk[sa[i - 1]]; |
| else rk[sa[i]] = i; |
| } |
| for (int l = 1; l <= n; l <<= 1) |
| { |
| tot = 0; |
| F(i, 1, n) if (sa[i] + l > n) tmp[++tot] = sa[i]; |
| F(i, 1, n) if (sa[i] > l) tmp[++tot] = sa[i] - l; |
| F(i, 1, n) pos[i] = 0; |
| F(i, 1, n) pos[rk[tmp[i]]] += 1; |
| F(i, 1, n) pos[i] += pos[i - 1]; |
| FF(i, n, 1) sa[pos[rk[tmp[i]]]--] = tmp[i]; |
| bool flg = 0; |
| F(i, 1, n) |
| { |
| if (i != 1 && rk[sa[i]] == rk[sa[i - 1]] |
| && rk[sa[i] + l] == rk[sa[i - 1] + l]) |
| { |
| tmp[sa[i]] = tmp[sa[i - 1]]; |
| flg = 1; |
| } |
| else tmp[sa[i]] = i; |
| } |
| F(i, 1, n) rk[i] = tmp[i]; |
| if (!flg) break; |
| } |
| } |
| } |
线代
矩阵
| namespace Matrix |
| { |
| constexpr int M = 3; |
| using T = int; |
| |
| struct Mat |
| { |
| T a[M][M]; |
| }; |
| struct Vec |
| { |
| T a[M]; |
| }; |
| |
| Mat operator *(const Mat &a, const Mat &b) |
| { |
| Mat t; |
| memset(t.a, 0, sizeof (t.a)); |
| F(i, 0, M - 1) F(k, 0, M - 1) |
| { |
| if (a.a[i][k] == 0) |
| { |
| continue; |
| } |
| F(j, 0, M - 1) |
| { |
| t.a[i][j] += a.a[i][k] * b.a[k][j]; |
| } |
| } |
| return t; |
| } |
| |
| Vec operator *(const Mat &a, const Vec &b) |
| { |
| Vec t; |
| memset(t.a, 0, sizeof (t.a)); |
| F(i, 0, M - 1) F(k, 0, M - 1) |
| { |
| t.a[i] += a.a[i][k] * b.a[k]; |
| } |
| return t; |
| } |
| |
| Mat mpow(const Mat &a, LL k) |
| { |
| Mat t, aa; |
| aa = a; |
| F(i, 0, M - 1) F(j, 0, M - 1) |
| { |
| t.a[i][j] = i == j ? 1 : 0; |
| } |
| while (k) |
| { |
| if (k & 1) |
| { |
| t = t * aa; |
| } |
| aa = aa * aa; |
| k >>= 1; |
| } |
| return t; |
| } |
| } |
数论
组合数
| LL kpow(LL x, LL k = MOD - 2) |
| { |
| x = x % MOD; |
| LL r = 1; |
| while (k) |
| { |
| if (k & 1) r = r * x % MOD; |
| x = x * x % MOD; |
| k >>= 1; |
| } |
| return r; |
| } |
| |
| int fac[N], ifac[N]; |
| |
| LL C(int n, int r) |
| { |
| if (r < 0 || r > n) return 0; |
| return fac[n] * (LL)ifac[n - r] % MOD * ifac[r] % MOD; |
| } |
| |
| void init_comb(int nn) |
| { |
| fac[0] = 1; |
| F(i, 1, nn) fac[i] = fac[i - 1] * (LL)i % MOD; |
| ifac[nn] = kpow(fac[nn]); |
| FF(i, nn, 1) ifac[i - 1] = ifac[i] * (LL)i % MOD; |
| } |
快速取模(Barrette Reduction)
| struct Barrate |
| { |
| __int128 m, t; |
| void init(int _m) |
| { |
| m = _m; |
| t = ((__int128)1 << 64) / m; |
| } |
| LL operator ()(LL x) |
| const { |
| return x - m * (x * t >> 64); |
| } |
| } pmod; |
| |
| LL kpow(LL x, LL k) |
| { |
| x = pmod(x); |
| LL r = 1; |
| while (k) |
| { |
| if (k & 1) r = pmod(r * x); |
| x = pmod(x * x); |
| k >>= 1; |
| } |
| return r; |
| } |
扩展欧几里得
| LL gcd(LL a, LL b) |
| { |
| LL t; |
| while (b) t = b, b = a % b, a = t; |
| return a; |
| } |
| |
| void exgcd(LL a, LL b, LL &x, LL &y) |
| { |
| if (b) exgcd(b, a % b, y, x), y -= a / b * x; |
| else x = 1, y = 0; |
| } |
| |
| LL calc_inv(LL a) |
| { |
| LL x, y; |
| exgcd(a, MOD, x, y); |
| return (x % MOD + MOD) % MOD; |
| } |
还原分数
| LL kpow(LL x, LL k, LL p) |
| { |
| LL r = 1; |
| while (k) |
| { |
| if (k & 1) r = (__int128)r * x % p; |
| x = (__int128)x * x % p; |
| k >>= 1; |
| } |
| return r; |
| } |
| |
| pair<LL, LL> recover(LL x, LL p) |
| { |
| vector<LL> a; |
| LL invx = kpow(x, p - 2, p), pp = p; |
| while (x) |
| { |
| a.push_back(x); |
| LL t = x; |
| x = p % x; |
| p = t; |
| } |
| pair<LL, LL> res{pp, pp}; |
| for (auto ca : a) |
| { |
| LL cb = (__int128)ca * invx % pp; |
| ca = min(ca, pp - ca); |
| cb = min(cb, pp - cb); |
| if (max(res.first, res.second) > max(ca, cb)) |
| res = {ca, cb}; |
| } |
| return res; |
| } |
Miller Rabin 与 Pollard's Rho
| constexpr int BS[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; |
| |
| mt19937_64 ran(chrono::system_clock::now().time_since_epoch().count()); |
| |
| LL kpow(LL x, LL k, LL mod) |
| { |
| LL r = 1; |
| while (k) |
| { |
| if (k & 1) r = (__int128)r * x % mod; |
| x = (__int128)x * x % mod; |
| k >>= 1; |
| } |
| return r; |
| } |
| |
| namespace MillerRabin |
| { |
| bool check(LL n) |
| { |
| if (n == 1) return false; |
| if (n == 2) return true; |
| if (n % 2 == 0) return false; |
| for (auto bs : BS) |
| { |
| if (n == bs) return true; |
| if (n % bs == 0) return false; |
| if (kpow(bs, n - 1, n) != 1) return false; |
| LL x = n - 1; |
| while (!(x & 1)) |
| { |
| x >>= 1; |
| LL t = kpow(bs, x, n); |
| if (t != 1) |
| { |
| if (t != n - 1) return false; |
| break; |
| } |
| } |
| } |
| return true; |
| } |
| } |
| |
| namespace PollardRho |
| { |
| LL get_factor(LL n) |
| { |
| if (n == 4) return 2; |
| uniform_int_distribution<LL> gen(1, n - 1); |
| while (1) |
| { |
| const LL c = gen(ran); |
| LL f = 0, ff = 0; |
| do { |
| LL pd = 1; |
| F(_, 1, 128) |
| { |
| f = ((__int128)f * f + c) % n; |
| ff = ((__int128)ff * ff + c) % n; |
| ff = ((__int128)ff * ff + c) % n; |
| if ((__int128)pd * abs(f - ff) % n == 0) break; |
| pd = (__int128)pd * abs(f - ff) % n; |
| } |
| LL g = __gcd(pd, n); |
| if (g != 1) return g; |
| } while (f != ff); |
| } |
| } |
| |
| vector<LL> solve(LL n) |
| { |
| if (MillerRabin::check(n)) return {n}; |
| LL x = get_factor(n); |
| auto res = solve(x); |
| auto r = solve(n / x); |
| res.insert(res.end(), r.begin(), r.end()); |
| return res; |
| } |
| } |
杜教筛
| namespace Phi |
| { |
| constexpr int M = (1 << 21) + 5; |
| |
| LL sg(LL n) |
| { |
| return n; |
| } |
| |
| LL sh(LL n) |
| { |
| return n * (n + 1) / 2; |
| } |
| |
| int nn; |
| LL sf[M]; |
| bool ispri[M]; |
| vector<int> pri; |
| |
| void init(int _n) |
| { |
| nn = _n; |
| ispri[1] = false; |
| F(i, 2, nn) ispri[i] = true; |
| sf[1] = 1; |
| F(i, 2, nn) |
| { |
| if (ispri[i]) |
| { |
| sf[i] = i - 1; |
| pri.push_back(i); |
| } |
| for (auto p : pri) |
| { |
| if (i * p > nn) break; |
| ispri[i * p] = false; |
| if (i % p == 0) |
| { |
| sf[i * p] = sf[i] * p; |
| break; |
| } |
| else sf[i * p] = sf[i] * (p - 1); |
| } |
| sf[i] += sf[i - 1]; |
| } |
| } |
| |
| unordered_map<LL, LL> mem; |
| |
| LL calc_sf(LL n) |
| { |
| if (n <= nn) return sf[n]; |
| if (mem.find(n) != mem.end()) return mem[n]; |
| LL ans = sh(n); |
| for (LL l = 2, r; l <= n; l = r + 1) |
| { |
| r = n / (n / l); |
| ans -= (sg(r) - sg(l - 1)) * calc_sf(n / l); |
| } |
| return mem[n] = ans; |
| } |
| } |
网络流
Dinic(有源汇网络最大流)
| namespace Dinic |
| { |
| constexpr int V = N * 2, E = N * N + N * 2; |
| using T = int; |
| |
| int nn; |
| struct Edge { int v; T cap, fw; } e[E << 1]; |
| int nxt_e[E << 1], hd_e[V], tot_e; |
| |
| void init(int n) |
| { |
| nn = n; |
| memset(hd_e + 1, -1, sizeof (int) * nn); |
| tot_e = 0; |
| } |
| |
| int ins_e(int u, int v, T c) |
| { |
| e[tot_e] = {v, c, 0}; |
| nxt_e[tot_e] = hd_e[u], hd_e[u] = tot_e++; |
| e[tot_e] = {u, 0, 0}; |
| nxt_e[tot_e] = hd_e[v], hd_e[v] = tot_e++; |
| return tot_e - 2; |
| } |
| |
| int lv[V]; |
| |
| bool bfs(int s, int t) |
| { |
| memset(lv + 1, -1, sizeof (int) * nn); |
| vector<int> qu; int fr = 0; |
| qu.push_back(t); lv[t] = 0; |
| while (fr < qu.size()) |
| { |
| int u = qu[fr++]; |
| for (int i = hd_e[u]; ~i; i = nxt_e[i]) |
| { |
| if (lv[e[i].v] != -1 || e[i ^ 1].cap == e[i ^ 1].fw) continue; |
| qu.push_back(e[i].v); lv[e[i].v] = lv[u] + 1; |
| } |
| } |
| return lv[s] != -1; |
| } |
| |
| int cur_hd[V]; |
| |
| T flow(int u, int t, T cf) |
| { |
| if (u == t) return cf; |
| T sum = 0; |
| for (; ~cur_hd[u]; cur_hd[u] = nxt_e[cur_hd[u]]) |
| { |
| int i = cur_hd[u]; |
| if (lv[e[i].v] != lv[u] - 1) continue; |
| T r = flow(e[i].v, t, min(cf - sum, e[i].cap - e[i].fw)); |
| sum += r; |
| e[i].fw += r, e[i ^ 1].fw -= r; |
| if (sum == cf) break; |
| } |
| return sum; |
| } |
| |
| T dinic(int s, int t) |
| { |
| T sum = 0; |
| while (bfs(s, t)) |
| { |
| memcpy(cur_hd + 1, hd_e + 1, sizeof (int) * (nn)); |
| sum += flow(s, t, numeric_limits<T>::max()); |
| } |
| return sum; |
| } |
| } |
费用流
这里都是 int
类型。
单路增广
| namespace CostFlow |
| { |
| constexpr int V = 5005, E = 50005; |
| |
| struct Edge |
| { |
| int v, cap, fl, w; |
| } e[E << 1]; |
| int nxt[E << 1], hd[V], tote; |
| |
| void clr(void) { tote = 0, memset(hd, -1, sizeof (hd)); } |
| |
| int ins_e(int u, int v, int c, int w) |
| { |
| e[tote] = {v, c, 0, w}; |
| nxt[tote] = hd[u], hd[u] = tote++; |
| e[tote] = {u, 0, 0, -w}; |
| nxt[tote] = hd[v], hd[v] = tote++; |
| return tote - 2; |
| } |
| |
| int from[V], dis[V]; bool inque[V]; |
| |
| bool spfa(int s, int t) |
| { |
| queue<int> que; que.push(t); |
| memset(dis, 0x3f, sizeof (dis)); dis[t] = 0; |
| memset(inque, 0, sizeof (inque)); inque[t] = 1; |
| from[s] = -1; |
| while (!que.empty()) |
| { |
| int u = que.front(); que.pop(); inque[u] = 0; |
| for (int i = hd[u]; i != -1; i = nxt[i]) |
| { |
| if (dis[e[i].v] <= dis[u] + e[i ^ 1].w |
| || e[i ^ 1].fl == e[i ^ 1].cap) continue; |
| dis[e[i].v] = dis[u] + e[i ^ 1].w; |
| from[e[i].v] = i ^ 1; |
| if (!inque[e[i].v]) inque[e[i].v] = 1, que.push(e[i].v); |
| } |
| } |
| return from[s] != -1; |
| } |
| |
| pair<int, int> flow(int s, int t) |
| { |
| int sf = 0, sw = 0; |
| while (spfa(s, t)) |
| { |
| int cf = INT_MAX, cw = 0; |
| for (int u = s; u != t; u = e[from[u]].v) |
| { |
| int id = from[u]; |
| MIN(cf, e[id].cap - e[id].fl); |
| cw += e[id].w; |
| } |
| sf += cf, sw += cf * cw; |
| for (int u = s; u != t; u = e[from[u]].v) |
| { |
| int id = from[u]; |
| e[id].fl += cf, e[id ^ 1].fl -= cf; |
| } |
| } |
| return {sf, sw}; |
| } |
| } |
多路增广
| namespace CostFlow |
| { |
| constexpr int V = 5005, E = 50005; |
| |
| struct Edge |
| { |
| int v, cap, fl, w; |
| } e[E << 1]; |
| int nxt[E << 1], hd[V], cur[V], tote; |
| |
| void clr(void) { tote = 0, memset(hd, -1, sizeof (hd)); } |
| |
| int ins_e(int u, int v, int c, int w) |
| { |
| e[tote] = {v, c, 0, w}; |
| nxt[tote] = hd[u], hd[u] = tote++; |
| e[tote] = {u, 0, 0, -w}; |
| nxt[tote] = hd[v], hd[v] = tote++; |
| return tote - 2; |
| } |
| |
| int from[V], dis[V]; bool inque[V]; |
| |
| bool spfa(int s, int t) |
| { |
| queue<int> que; que.push(t); |
| memset(dis, 0x3f, sizeof (dis)); dis[t] = 0; |
| memset(inque, 0, sizeof (inque)); inque[t] = 1; |
| from[s] = -1; |
| while (!que.empty()) |
| { |
| int u = que.front(); que.pop(); inque[u] = 0; |
| for (int i = hd[u]; i != -1; i = nxt[i]) |
| { |
| if (dis[e[i].v] <= dis[u] + e[i ^ 1].w |
| || e[i ^ 1].fl == e[i ^ 1].cap) continue; |
| dis[e[i].v] = dis[u] + e[i ^ 1].w; |
| from[e[i].v] = i ^ 1; |
| if (!inque[e[i].v]) inque[e[i].v] = 1, que.push(e[i].v); |
| } |
| } |
| return from[s] != -1; |
| } |
| |
| vector<int> rst; |
| bool vis[V]; |
| |
| pair<int, int> go_flow(int u, int t, int sf) |
| { |
| if (u == t) return {sf, 0}; |
| rst.push_back(u); |
| vis[u] = 1; |
| int cf = 0, cw = 0; |
| for (int &i = cur[u]; i != -1; i = nxt[i]) |
| { |
| if (e[i].cap == e[i].fl || dis[e[i].v] + e[i].w != dis[u] |
| || vis[e[i].v]) continue; |
| auto ret = go_flow(e[i].v, t, min(e[i].cap - e[i].fl, sf - cf)); |
| int tf = ret.first; |
| cf += tf; |
| cw += ret.second + tf * e[i].w; |
| e[i].fl += tf, e[i ^ 1].fl -= tf; |
| if (cf == sf) break; |
| } |
| vis[u] = 0; |
| return {cf, cw}; |
| } |
| |
| pair<int, int> flow(int s, int t) |
| { |
| int sf = 0, sw = 0; |
| memcpy(cur, hd, sizeof (cur)); |
| while (spfa(s, t)) |
| { |
| auto ret = go_flow(s, t, INT_MAX); |
| sf += ret.first, sw += ret.second; |
| for (int u : rst) cur[u] = hd[u]; |
| rst.clear(); |
| } |
| return {sf, sw}; |
| } |
| } |
Capcity Scaling
真正的(弱)多项式复杂度 的费用流,然而会跑很满,在多数 CNOI 费用流题目中无法通过。
最小费用最大流需要一些手动操作,封装不太好。
| |
| |
| |
| |
| #include <bits/stdc++.h> |
| |
| using namespace std; |
| |
| using LL = long long; |
| using ULL = unsigned long long; |
| |
| #define F(i, l, r) for (int i = (l); i <= (r); ++i) |
| #define FF(i, r, l) for (int i = (r); i >= (l); --i) |
| #define MAX(a, b) ((a) = max(a, b)) |
| #define MIN(a, b) ((a) = min(a, b)) |
| #define SZ(a) ((int)((a).size()) - 1) |
| |
| namespace CostFlow |
| { |
| constexpr int V = 505, E = 505; |
| |
| struct Edge |
| { |
| int u, v; LL cap, ccap, fl, w; |
| } e[E << 1]; |
| int nxt[E << 1], hd[V], cur[V], tote; |
| |
| void clr(void) { tote = 0, memset(hd, -1, sizeof (hd)); } |
| |
| int ins_e(int u, int v, LL c, LL w) |
| { |
| e[tote] = {u, v, c, 0, 0, w}; |
| nxt[tote] = hd[u], hd[u] = tote++; |
| e[tote] = {v, u, 0, 0, 0, -w}; |
| nxt[tote] = hd[v], hd[v] = tote++; |
| return tote - 2; |
| } |
| |
| int from[V]; LL dis[V]; bool inque[V]; |
| |
| bool spfa(int s, int t) |
| { |
| queue<int> que; que.push(t); |
| memset(dis, 0x3f, sizeof (dis)); dis[t] = 0; |
| memset(inque, 0, sizeof (inque)); inque[t] = 1; |
| from[s] = -1; |
| while (!que.empty()) |
| { |
| int u = que.front(); que.pop(); inque[u] = 0; |
| for (int i = hd[u]; i != -1; i = nxt[i]) |
| { |
| if (dis[e[i].v] <= dis[u] + e[i ^ 1].w |
| || e[i ^ 1].fl == e[i ^ 1].ccap) continue; |
| dis[e[i].v] = dis[u] + e[i ^ 1].w; |
| from[e[i].v] = i ^ 1; |
| if (!inque[e[i].v]) inque[e[i].v] = 1, que.push(e[i].v); |
| } |
| } |
| return from[s] != -1; |
| } |
| |
| pair<LL, LL> flow(void) |
| { |
| LL sf = 0, sw = 0; |
| int mxk = 0; |
| for (int i = 0; i < tote; i += 2) while (e[i].cap >> mxk) ++mxk; |
| FF(k, mxk - 1, 0) |
| { |
| sf <<= 1, sw <<= 1; |
| F(i, 0, tote - 1) e[i].ccap <<= 1, e[i].fl <<= 1; |
| |
| for (int i = 0; i < tote; i += 2) if (e[i].cap >> k & 1) |
| { |
| if (!spfa(e[i].v, e[i].u) || dis[e[i].v] + e[i].w >= 0) |
| { |
| ++e[i].ccap; |
| continue; |
| } |
| ++e[i].ccap; |
| ++e[i].fl, --e[i ^ 1].fl; |
| for (int u = e[i].v; u != e[i].u; u = e[from[u]].v) |
| ++e[from[u]].fl, --e[from[u] ^ 1].fl; |
| ++sf, sw += dis[e[i].v] + e[i].w; |
| } |
| } |
| return {sf, sw}; |
| } |
| } |
| |
| signed main(void) |
| { |
| |
| |
| ios::sync_with_stdio(0), cin.tie(nullptr); |
| |
| int n, m, s, t; cin >> n >> m >> s >> t; |
| CostFlow::clr(); |
| LL ex = 0, sum_c = 0, sum_w = 0; |
| F(i, 1, m) |
| { |
| int u, v; LL c, w; cin >> u >> v >> c >> w; |
| if (u == v) |
| { |
| if (w < 0) ex += w * c; |
| continue; |
| } |
| sum_c += c; |
| sum_w += abs(w); |
| CostFlow::ins_e(u, v, c, w); |
| } |
| int ts = CostFlow::ins_e(t, s, sum_c, -sum_w - 1); |
| LL res = CostFlow::flow().second; |
| res -= CostFlow::e[ts].fl * CostFlow::e[ts].w; |
| cout << CostFlow::e[ts].fl << ' ' << res + ex << endl; |
| |
| return 0; |
| } |
计算几何
向量
| struct Vec |
| { |
| double x, y; |
| |
| double len(void) const { return sqrt(x * x + y * y); } |
| double angle(void) const { return atan2(y, x); } |
| |
| Vec operator +(const Vec& o) const { return {x + o.x, y + o.y}; } |
| Vec& operator +=(const Vec& o) |
| { |
| x += o.x, y += o.y; |
| return *this; |
| } |
| Vec operator -(const Vec& o) const { return {x - o.x, y - o.y}; } |
| Vec& operator -=(const Vec& o) |
| { |
| x -= o.x, y -= o.y; |
| return *this; |
| } |
| |
| friend Vec operator *(const Vec& v, double p) { return {v.x * p, v.y * p}; } |
| friend Vec operator *(double p, const Vec& v) { return {v.x * p, v.y * p}; } |
| Vec& operator *= (double p) |
| { |
| x *= p, y *= p; |
| return *this; |
| } |
| friend Vec operator /(const Vec& v, double p) { return {v.x / p, v.y / p}; } |
| friend Vec operator /(double p, const Vec& v) { return {v.x / p, v.y / p}; } |
| Vec& operator /= (double p) |
| { |
| x /= p, y /= p; |
| return *this; |
| } |
| |
| double dot(const Vec& o) const { return x * o.x + y * o.y; } |
| double times(const Vec& o) const { return x * o.y - y * o.x; } |
| }; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下