【扯淡】各种模版

    · 博主某天心情好

    · 代码还是很自豪的≥ 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];
            }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值