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
- MST
- MST
- MST......
- mst
- MST
- MST
- MST
- 【MST】MST唯一性
- PVST+,MST
- POJ1251 MST
- hdu1102(MST)
- 初识MST
- ZOJ1872Freckles(MST)
- hdu1598 MST
- MST性质
- MST补充
- Prim【MST】
- Kruskal【MST】
- Predict the Winner
- 日期格式DateFormat使用
- sed命令入门及进阶
- dot-files/directories 点开头的文件或文件夹(windows/linux)
- Visual Studio Code 常用快捷键
- MST
- java导出百万级数据到excel解决方案
- 编写一个函数实现n^k,使用递归实现
- 面试官谈游戏开发入行--技术准备
- 109. Convert Sorted List to Binary Search Tree(补上周)
- [问题] 阿里云无法telnet端口 连接失败 无法进行TCP通信
- c++第五次上机作业
- 我真的懂java吗(一)
- SonicOperator之相关工作1