文件源和模板

基本

文件头

// Author: kyEEcccccc

#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)
{
	// freopen(".in", "r", stdin);
	// freopen(".out", "w", stdout);
	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--]);
	}
}

自动对拍

// Author: kyEEcccccc

#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)
{
	// freopen(".in", "r", stdin);
	// freopen(".out", "w", stdout);
	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

真正的(弱)多项式复杂度 \(\mathrm O(nm^2\log U)\) 的费用流,然而会跑很满,在多数 CNOI 费用流题目中无法通过。

最小费用最大流需要一些手动操作,封装不太好。



// Author: kyEEcccccc

#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)
{
	// freopen(".in", "r", stdin);
	// freopen(".out", "w", stdout);
	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; }
};
posted @ 2023-02-03 12:26  kyEEcccccc  阅读(108)  评论(0编辑  收藏  举报