[BZOJ3669][NOI2014]魔法森林(LCT)
来源:互联网 发布:浪漫主义文学 知乎 编辑:程序博客网 时间:2024/05/18 02:19
直接求解比较麻烦。考虑先按照
看到动态加边,可以想到使用LCT来完成。由于要维护边权,所以要把边在LCT中理解成点。
但是现在的一个问题是出现环时应该怎样处理。假设现在要连边
连边之后,即可询问
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}const int N = 2e5 + 5;int n, m, fa[N], lc[N], rc[N], rev[N], que[N], len, val[N], sm[N],f[N];struct cyx {int a, b, x, y;} ask[N];int cx(int x) { if (f[x] != x) f[x] = cx(f[x]); return f[x];}void zm(int x, int y) { int ix = cx(x), iy = cx(y); if (ix != iy) f[iy] = ix;}bool comp(cyx a, cyx b) {return a.y < b.y;}int which(int x) {return rc[fa[x]] == x;}bool is_root(int x) { return !fa[x] || (lc[fa[x]] != x && rc[fa[x]] != x);}void upt(int x) { sm[x] = x; if (lc[x] && val[sm[lc[x]]] > val[sm[x]]) sm[x] = sm[lc[x]]; if (rc[x] && val[sm[rc[x]]] > val[sm[x]]) sm[x] = sm[rc[x]];}void down(int x) { if (rev[x]) { swap(lc[x], rc[x]); if (lc[x]) rev[lc[x]] ^= 1; if (rc[x]) rev[rc[x]] ^= 1; rev[x] = 0; }} void rotate(int x) { int y = fa[x], z = fa[y], b = lc[y] == x ? rc[x] : lc[x]; if (z && !is_root(y)) (lc[z] == y ? lc[z] : rc[z]) = x; fa[x] = z; fa[y] = x; b ? fa[b] = y : 0; if (lc[y] == x) rc[x] = y, lc[y] = b; else lc[x] = y, rc[y] = b; upt(y); upt(x);}void splay(int x) { int i, y; que[len = 1] = x; for (y = x; !is_root(y); y = fa[y]) que[++len] = fa[y]; for (i = len; i >= 1; i--) down(que[i]); while (!is_root(x)) { if (!is_root(fa[x])) { if (which(x) == which(fa[x])) rotate(fa[x]); else rotate(x); } rotate(x); } upt(x);}void Access(int x) { int y; for (y = 0; x; y = x, x = fa[x]) { splay(x); rc[x] = y; if (y) fa[y] = x; upt(x); }}int Find_Root(int x) { Access(x); splay(x); while (down(x), lc[x]) x = lc[x]; splay(x); return x;}void Make_Root(int x) { Access(x); splay(x); rev[x] ^= 1;}void Link(int x, int y) { Make_Root(x); fa[x] = y;}void Cut(int x, int y) { Make_Root(x); Access(y); splay(y); lc[y] = 0; fa[x] = 0; upt(y);}int Select(int x, int y) { Make_Root(x); Access(y); splay(y); return sm[y];}int main() { int i, ans = 2e9; n = read(); m = read(); for (i = 1; i <= m; i++) ask[i].a = read(), ask[i].b = read(), ask[i].x = read(), ask[i].y = read(); sort(ask + 1, ask + m + 1, comp); for (i = 1; i <= n + m; i++) f[i] = sm[i] = i; for (i = n + 1; i <= n + m; i++) val[i] = ask[i - n].x; for (i = 1; i <= m; i++) { int u = ask[i].a, v = ask[i].b; bool flag = 1; if (cx(u) == cx(v)) { int w = Select(u, v); if (val[w] > ask[i].x) Cut(ask[w - n].a, w), Cut(w, ask[w - n].b); else flag = 0; } else zm(u, v); if (flag) Link(u, i + n), Link(i + n, v); if (cx(1) == cx(n)) ans = min(ans, ask[i].y + val[Select(1, n)]); } if (ans < 2e9) printf("%d\n", ans); else printf("-1\n"); return 0;}
阅读全文
0 0
- BZOJ3669: [Noi2014]魔法森林(LCT)
- [BZOJ3669][NOI2014]魔法森林(LCT)
- bzoj3669: [Noi2014]魔法森林 LCT
- [BZOJ3669][Noi2014]魔法森林 && LCT
- 【bzoj3669】[Noi2014]魔法森林 LCT
- 【BZOJ3669】【NOI2014】魔法森林 LCT
- [BZOJ3669][Noi2014]魔法森林(并查集+LCT)
- [BZOJ3669][UOJ#3][Noi2014][LCT]魔法森林
- BZOJ3669 [Noi2014]魔法森林
- bzoj3669: [Noi2014]魔法森林
- [BZOJ3669][Noi2014]魔法森林
- 【NOI2014】【BZOJ3669】魔法森林
- [bzoj3669][NOI2014]魔法森林
- BZOJ3669: [Noi2014]魔法森林
- bzoj3669: [Noi2014]魔法森林
- BZOJ3669: [Noi2014]魔法森林
- bzoj3669 [Noi2014]魔法森林
- 【NOI2014】bzoj3669 魔法森林
- jvm内存分配技术
- C语言经典项目之二——扫雷
- 1自己常用Linux常用命令
- S5PV210的启动过程详解(一)
- 【洛谷2982】[Usaco2010 Feb]慢下来Slowdown(dfs序+线段树)
- [BZOJ3669][NOI2014]魔法森林(LCT)
- python 解析xml,并修改,插入标签。以及出现ns0的问题,和缩进问题。
- 在Dialog布局中添加ListView
- jquery 获取textarea文本值详解
- [BZOJ4475][JSOI2015]子集选取(DP+结论)
- 1自己常用windows命令
- SLAM方法汇总
- java 行为模式 状态模式
- SpringBoot入门-3(返回json数据)