MST

来源:互联网 发布:mac 微软雅黑字体关了 编辑:程序博客网 时间:2024/05/27 09:44

模板。

#include <bits/stdc++.h>using namespace std;#define N 100010#define M 1000010#define ULL unsigned long long#define LL long long#define ls (i << 1)#define rs (ls | 1)#define md ((ll + rr) >> 1)#define lson ll, md, ls#define rson md + 1, rr, rs#define inf 0x3f3f3f3f#define eps 1e-6#define pii pair<int, int>#define MP make_pair#define mod 1000000007#define sqr(x) ((x) * (x))int dcmp(double x) {    if (fabs(x) < eps) return 0;    return x < 0 ? -1 : 1;}struct point {    double x, y;    int id;    struct Edge *e;    bool operator < (const point & p) const {        return dcmp(x - p.x) != 0 ? x < p.x : dcmp(y - p.y) < 0;    }    bool operator == (const point & p) const {            return dcmp(x - p.x) == 0 && dcmp(y - p.y) == 0;    }    void input(int i) {        id = i;        scanf("%lf%lf", &x, &y);    }}p[N];double cross(point & o, point & a, point & b) {    return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);}double dot(point & o, point & a, point & b) {    return (a.x - o.x) * (b.x - o.x) + (a.y - o.y) * (b.y - o.y);}double dis(point a, point b) {    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}struct Edge {    point *o, *d;    Edge *on, *op, *dn, *dp;};#define Op(e,p) ((e)->o==p?(e)->d:(e)->o)#define Next(e,p) ((e)->o==p?(e)->on:(e)->dn)#define Prev(e,p) ((e)->o==p?(e)->op:(e)->dp)struct Delaunay {    void solve(point * ps, int n) { //点集需要 sort 和 unique        sort(ps, ps + n);        edge_num = 0;        rubb = NULL;        for (int i = 0; i < n; i++) ps[i].e = NULL;        Edge* l_cw, *r_ccw;        divide(ps, 0, n, l_cw, r_ccw);    }    Edge es[M], *rubb;    int edge_num;    Edge *make_edge(point &u, point &v) {        Edge * e;        if (rubb == NULL) {            e = es + edge_num++;        }        else {            e = rubb;            rubb = rubb->dn;        }        e->on = e->op = e->dn = e->dp = e;        e->o = &u; e->d = &v;        if (u.e == NULL) u.e = e;        if (v.e == NULL) v.e = e;        return e;    }    void delete_edge(Edge *e) {        point *u = e->o, *v = e->d;        if (u->e == e) u->e = e->on;        if (v->e == e) v->e = e->dn;        Prev(e->on, u) = e->op;        Next(e->op, u) = e->on;        Prev(e->dn, v) = e->dp;        Next(e->dp, v) = e->dn;        e->dn = rubb;        rubb = e;    }    void splice(Edge *a, Edge *b, point *v) {        Edge *n;        n = Next(a, v); Next(a, v) = b;        Prev(n, v) = b;        Next(b, v) = n; Prev(b, v) = a;    }    Edge *join(Edge *a, point *u, Edge *b, point *v, int s) {        Edge *e = make_edge(*u, *v);        if (s == 0) {            splice(Prev(a, u), e, u);            splice(b, e, v);        }        else {            splice(a, e, u);            splice(Prev(b, v), e, v);        }        return e;    }    void lower_tangent(Edge * & l, Edge * & r, point * & s, point * & u) {        point *dl = Op(l, s), *dr = Op(r, u);        while (1) {            if (dcmp(cross((*s), (*dl), (*u))) > 0) {                    l = Prev(l, dl); s = dl; dl = Op(l, s);            }            else if (dcmp(cross((*u), (*dr), (*s))) < 0) {                r = Next(r, dr); u = dr; dr = Op(r, u);            }            else break;        }    }    void merge(Edge *r_cw_l, point *s, Edge *l_ccw_r, point *u, Edge        **l_tangent) {        Edge *b, *lc, *rc;        point *dlc, *drc;        double crc, clc;        lower_tangent(r_cw_l, l_ccw_r, s, u);        b = join(r_cw_l, s, l_ccw_r, u, 1);        *l_tangent = b;        do {            lc = Next(b, s); rc = Prev(b, u); dlc = Op(lc, s); drc = Op(rc, u);            double cplc = cross(*dlc, *s, *u);            double cprc = cross(*drc, *s, *u);            bool alc = dcmp(cplc)>0, arc = dcmp(cprc)>0;            if (!alc && !arc) break;            if (alc) {                clc = dot(*dlc, *s, *u) / cplc;                do {                    Edge * next = Next(lc, s);                    point & dest = *Op(next, s);                    double cpn = cross(dest, *s, *u);                    if (dcmp(cpn) <= 0) break;                    double cn = dot(dest, *s, *u) / cpn;                    if (dcmp(cn - clc)>0) break;                    delete_edge(lc);                    lc = next;                    clc = cn;                } while (1);            }            if (arc) {                crc = (double)dot(*drc, *s, *u) / cprc;                do {                    Edge * prev = Prev(rc, u);                    point & dest = *Op(prev, u);                    double cpp = cross(dest, *s, *u);                    if (dcmp(cpp) <= 0) break;                    double cp = dot(dest, *s, *u) / cpp;                    if (dcmp(cp - crc) > 0) break;                    delete_edge(rc);                    rc = prev;                    crc = cp;                } while (1);            }            dlc = Op(lc, s); drc = Op(rc, u);            if (!alc || (alc && arc && dcmp(crc - clc) < 0)) {                b = join(b, s, rc, drc, 1);                u = drc;            }            else {                b = join(lc, dlc, b, u, 1);                s = dlc;            }        } while (1);    }    void divide(point *p, int l, int r, Edge * & l_ccw, Edge * & r_cw) {        int n = r - l;        Edge *l_ccw_l, *r_cw_l, *l_ccw_r, *r_cw_r, *l_tangent, *c;        if (n == 2) {            l_ccw = r_cw = make_edge(p[l], p[l + 1]);        }        else if (n == 3) {            Edge * a = make_edge(p[l], p[l + 1]), *b = make_edge(p[l + 1], p[l + 2]);            splice(a, b, &p[l + 1]);            double c_p = cross(p[l], p[l + 1], p[l + 2]);            if (dcmp(c_p)>0) {                c = join(a, &p[l], b, &p[l + 2], 1); l_ccw = a; r_cw = b;            }            else if (dcmp(c_p) < 0) {                c = join(a, &p[l], b, &p[l + 2], 0); l_ccw = c; r_cw = c;            }            else {                l_ccw = a; r_cw = b;            }        }        else if (n > 3) {            int split = (l + r) / 2;            divide(p, l, split, l_ccw_l, r_cw_l);            divide(p, split, r, l_ccw_r, r_cw_r);            merge(r_cw_l, &p[split - 1], l_ccw_r, &p[split], &l_tangent);            if (l_tangent->o == &p[l]) l_ccw_l = l_tangent;            if (l_tangent->d == &p[r - 1]) r_cw_r = l_tangent;            l_ccw = l_ccw_l; r_cw = r_cw_r;        }    }} de;struct tree_edge {    int u, v;    double c;    tree_edge(int u = 0, int v = 0, double c = 0) : u(u), v(v), c(c) {}    bool operator < (const tree_edge &b) const {        return c < b.c;    }}tree_e[M];void addEdge(int &k, int u, int v, double d) {    tree_e[++k] = tree_edge(u, v, d);}void getEdge(int &k, int n) {    k = 0;    Edge *st, *cur;    point *u, *v;    for (int i = 0; i < n; ++i) {        u = &pnt[i];        st = cur = u->e;        do {            v = Op(cur, u);            if (u < v)                addEdge(k, u->id, v->id, dis(*u, *v));        } while ((cur = Next(cur, u)) != st);    }}void enum_triangle(point *ps, int n) {    Edge *e_start, *e, *nxt;    point *u, *v, *w;    for (int i = 0; i < n; i++) {        u = &ps[i];        e_start = e = u->e;        do {            v = Op(e, u);            if (u < v) {                nxt = Next(e, u);                w = Op(nxt, u);                if (u < w && Next(nxt, w) == Prev(e, v)) {                    // now, (u v w) is a triangle!!!!!!                    // 这时,uvw 的外接圆是空的(不包含 ps 中的其他点),如果要求最大空圆,则计算 uvw 的外接圆就可以!                }            }        } while ((e = Next(e, u)) != e_start);    }}int n, fa[N];struct LCA{    int fst[N], vv[M], nxt[M], dep[N], e;    double cost[M], fee[N][22];    int fa[N][22];    void init(){        memset(fst, -1, sizeof fst); e = 0;    }    void add(int u, int v, double c){        vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;    }    void dfs(int u, int p, int d, double c){        fa[u][0] = p, dep[u] = d, fee[u][0] = c;        for(int i = fst[u]; ~i; i = nxt[i]){            int v = vv[i];            if(v == p) continue;            dfs(v, u, d + 1, cost[i]);        }    }    void init_lca(){        for(int k = 0; k < 21; ++k)            for(int i = 1; i <= n; ++i){                if(fa[i][k] == -1)                    fa[i][k+1] = -1, fee[i][k+1] = fa[i][k];                else                    fa[i][k+1] = fa[fa[i][k]][k],                    fee[i][k+1] = max(fee[i][k], fee[fa[i][k]][k]);            }    }    double lca(int u, int v){        double ret = 0;        if(dep[u] > dep[v]) swap(u, v);        for(int i = 0; i < 21; ++i)            if((dep[v] - dep[u]) >> i & 1){                ret = max(ret, fee[v][i]);                v = fa[v][i];            }        if(v == u) return ret;        for(int i = 21; i >= 0; --i)            if(fa[u][i] != fa[v][i]){                ret = max(ret, fee[u][i]);                ret = max(ret, fee[v][i]);                u = fa[u][i], v = fa[v][i];            }        ret = max(ret, fee[u][0]);        ret = max(ret, fee[v][0]);        return ret;    }}go;int find(int u){    if(fa[u] != u) fa[u] = find(fa[u]);    return fa[u];}int main() {    do{        scanf("%d", &n);        for (int i = 0; i < n; ++i) {            scanf("%lf%lf", &pnt[i].x, &pnt[i].y);            pnt[i].id = i + 1;        }        de.solve(pnt, n);        int k = 0;        getEdge(k, n);        sort(tree_e + 1, tree_e + 1 + k);        for(int i = 0; i <= n; ++i) fa[i] = i;        double ans = 0;        go.init();        for (int i = 1; i <= k; ++i){            int u = tree_e[i].u, v = tree_e[i].v;            double c = tree_e[i].c;            int fu = find(u), fv = find(v);            if(fu == fv) continue;            fa[fu] = fv;            go.add(u, v, c);            go.add(v, u, c);            ans += c;        }        go.dfs(1, -1, 0, 0);        go.init_lca();        int m;        scanf("%d", &m);        while(m--){            int u, v;            scanf("%d%d", &u, &v);            printf("%.6f\n", go.lca(u, v));        }    }while(0);    return 0;}
0 0
原创粉丝点击