· 博主某天心情好
· 代码还是很自豪的≥ v ≤ ~
· 鸣谢Delayyy君
嗯……
为了报 (zao) 复 (fu) 社 (ren) 会 (lei).
其实是懒得再去文件夹里翻来翻去了……
于是就放点模版过来……
二叉堆 < 带堆外指向标记 >
nowp:当前堆大小
pos : 堆外指向标记 ( 指向堆内位置 )
exp : 堆内节点标记 ( 指向堆外元素 )
cmp (A, B) :比较A, B, 返回 true 表示 A 应当放 B 上面.
void up(int p)
{
int j, last = exp[p];
for (j = p; p >>= 1, p && cmp(last, exp[p]); j = p)
exp[j] = exp[p], pos[exp[j]] = j;
exp[j] = last; pos[exp[j]] = j;
}
void down(int p)
{
int j, last = exp[p];
for (j = p; p <<= 1, p <= nowp && cmp(exp[p], last) || p < nowp && cmp(exp[p + 1], last);
exp[j] = exp[p], pos[exp[j]] = j, j = p)
if (p < nowp && cmp(exp[p + 1], exp[p])) ++p;
exp[j] = last; pos[exp[j]] = j;
}
void change(int p)
{
if (p != 1 && cmp(exp[p], exp[p >> 1])) up(p);
else down(p);
}
网络流 < Dinic >
鸣谢Delayyy君 ~
应该是比较好的 Dinic 模版了. 跑各种构造数据都还理想.
dima :高度标记
t :lazy 式 vis 标记, 判断是否登记在本次增广中.
edv :边容量
c、g、next:挂链用的, 作用没必要说了吧……
map 、gp :当前弧优化, 不想用删掉就没问题了
sta、ent :源、汇
void Add(int x, int y, int t)
{
c[++sg] = y, next[sg] = g[x], g[x] = sg, edv[sg] = t;
c[++sg] = x, next[sg] = g[y], g[y] = sg, edv[sg] = 0;
}
bool BFS(int z)
{
int tail, v;
tail = 1; p[1] = z; t[z] = ++set; dima[z] = 0;
for (int i = 1; i <= tail; ++i)
for (int x = g[p[i]]; x; x = next[x])
if (t[c[x]] < set && edv[x ^ 1])
{
t[c[x]] = set, p[++tail] = c[x], dima[c[x]] = dima[p[i]] + 1;
if (c[x] == sta) return true;
}
return false;
}
int DFS(int z, int push)
{
int flow = 0, f;
if (z == ent || !push) return push;
for (int x = map[z] == set ? gp[z] : gp[z] = g[z]; x; gp[z] = next[gp[z]], x = next[x])
if (t[c[x]] == set && dima[z] == dima[c[x]] + 1)
if (edv[x] && (f = DFS(c[x], edv[x] > push ? push : edv[x])))
{
edv[x] -= f, edv[x ^ 1] += f; push -= f; flow += f;
if (!push) return map[z] = set, flow;
}
dima[z] = INF;
return map[z] = set, flow;
}
计算几何 < 更新向量叉乘、点积, 旋转, 直线交点、直线圆交点、圆切线 >
13.3.16 今天被某神题坑爆了……
为了个精度误差纠结了好久. ( Delayyy君表示精度误差什么的都是浮云, Orz )
而且脑抽求向量夹角用asin ( asin取值范围不是 (-π/2, π/2 ) 么 ? ⑨ 啊 ⑨ )
目前出现的精度误差多了去了……大概总结一下:
1、 sqrt ( A - B ) 需要 + abs, ( 一般不用啦……只是有些时候会很坑爹而已 )
2、 acos ( A ) A 需要控制下精度问题…… 出现 1.000000002 或 -1.0000000002什么的太尴尬了.
3、 0 周围的各种 e-14~e-16. 按照问题实际要求处理... (不然什么极角排序时明明是 0 出现个 -1.23e-16 会非常非常……头疼 )
求大神解决以上问题啊T T
13.3.17 很不甘心地求了Delayyy君的程序…… (为什么精度没问题啊魂淡> <~)
结果喜闻乐见也萎了 ? !
唯一的区别就是 WinXp 和 Linux .....
Win的精度真是不可捉的东西啊……= =、
struct point { double x, y; }; // 点
struct line { point a, b; }; // 线 ( 三种均可...... )
struct circle { point z; double r; }; // 圆
double cx(point o, point a, point b) { return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); } // 叉积
double dj(point o, point a, point b) { return (a.x - o.x) * (b.x - o.x) + (a.y - o.y) * (b.y - o.y); } // 点积
double dist(point a, point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } // 距离公式
line rota(line a, double rev) // 向量旋转
{
double c = cos(rev), s = sin(rev);
return (line) {a.a, (point) {a.a.x + c * (a.b.x - a.a.x) - s * (a.b.y - a.a.y), a.a.y + c * (a.b.y - a.a.y) + s * (a.b.x - a.a.x)}};
}
point line_cross(line a, line b) // 两条直线交点
{
double sep = cx(a.a, b.a, b.b), seq = cx(a.b, b.a, b.b); sep = sep / (sep - seq);
return (point) {a.a.x + (a.b.x - a.a.x) * sep, a.a.y + (a.b.y - a.a.y) * sep};
}
line circle_line(circle a, line b) // 圆与直线交点, 返回一个点集合, 点数为 2 ( 切线返回 2个相同的点 , 其实会有坑爹的精度误差..... )
{ // 具体方法是:求出圆心在直线上的投影坐标, 然后求出弦长, 加加减减就可以了
line c = rota(b, pi / 2);
c.b = (point) {a.z.x - c.a.x + c.b.x, c.b.y = a.z.y - c.a.y + c.b.y}; c.a = a.z;
point p = line_cross(c, b);
double d = dist(a.z, p) - eps; // 如果 b 正好是圆 a 的切线的话, dist(a.z, p) 很有可能会因为精度误差导致 > a.r
d = sqrt(a.r * a.r - d * d);
double e = dist(b.a, b.b);
double x = (d / e) * (b.a.x - b.b.x), y = (d / e) * (b.a.y - b.b.y);
return (line) { (point) {p.x - x, p.y - y}, (point) {p.x + x, p.y + y} };
}
line circle_point(circle a, point b) // 圆切线, 返回一个点集合, 点数为 2 ( 圆的 2 个切点 )
{ // 具体求法 : 求出切线与圆心连线的夹角然后加加减减......
line p; p.a = b; p.b = a.z; double ps = dist(a.z, b);
double lpc = asin(a.r / ps); // 这里还是可以用asin滴...> <
line aw = rota(p, -lpc), bw = rota(p, lpc);
return (line) {aw.b, bw.b};
}
高斯消元 < . >
再次鸣谢Delayyy君
好久没写过了怒补一次……
话说代码风格感觉又变了> <~ ( 不就多打了几个回车么...)
for (int i = 1; i <= n; ++i)
{
double minp = -1; int w;
for (int j = i; j <= n; ++j)
if (abs(p[j][i]) > eps)
if (minp - abs(p[j][i]) < eps) minp = abs(p[j][i]), w = j;
if (i != w)
for (int j = 0; j++ <= n; )
swap(p[i][j], p[w][j]);
for (int j = i + 1; j <= n; ++j)
{
double lap = p[j][i] / p[i][i];
for (int k = i - 1; k++ <= n; )
p[j][k] = p[j][k] - p[i][k] * lap;
}
}
for (int i = n; i; --i)
{
p[i][i] = p[i][n + 1] / p[i][i];
for (int j = i - 1; j; --j)
p[j][n + 1] -= p[i][i] * p[j][i];
}