[BZOJ2816][ZJOI2012]网络(LCT)
2017-08-26 08:10
519 查看
如果对LCT(Link-Cut Tree)不了解,请参考链接http://www.cnblogs.com/BLADEVIL/p/3510997.html。
对于每一种颜色,维护一个LCT(因为没有同色的环,且C<=10)。每种颜色对应的LCT中包含所有的点,但只包含对应颜色的边。
对于操作0,就是修改点权,也就是Splay上的操作,就不多说了(要注意一点,每一种颜色对应的LCT上的节点x都要修改)。
对于操作2,就是找出对应颜色的LCT,提取路径并询问路径最大值,这也不多说了。
而重点就是操作1。
对于判断一条边是否存在,可以使用map来判定,当然暴力枚举也可以(因为由限制条件1可得,与一个点相连的边数不超过2∗C)。
在这里我不知道数据中会不会出现「一条边修改成这条边当前的颜色」的情况,所以我判定了一下,如果出现这种情况就直接判定为同时满足限制条件1和2并continue。
对于判断是否满足限制条件1,可以使用统计的方法,即统计与每个点相连的每种颜色的边有几条,如果节点u和v中至少有一个点相连的颜色为w的边数等于2,那么限制条件1不满足。
对于限制条件2,直接判断在颜色w对应的LCT中,是否FindRoot(u)==FindRoot(v),如果是则限制条件2不满足。
如果同时满足限制条件1和2,则维护一下统计数组,然后在这条边原来的颜色对应的LCT中,执行Cut(u,v),再在颜色w对应的LCT中,执行Link(u,v)。
代码:
对于每一种颜色,维护一个LCT(因为没有同色的环,且C<=10)。每种颜色对应的LCT中包含所有的点,但只包含对应颜色的边。
对于操作0,就是修改点权,也就是Splay上的操作,就不多说了(要注意一点,每一种颜色对应的LCT上的节点x都要修改)。
对于操作2,就是找出对应颜色的LCT,提取路径并询问路径最大值,这也不多说了。
而重点就是操作1。
对于判断一条边是否存在,可以使用map来判定,当然暴力枚举也可以(因为由限制条件1可得,与一个点相连的边数不超过2∗C)。
在这里我不知道数据中会不会出现「一条边修改成这条边当前的颜色」的情况,所以我判定了一下,如果出现这种情况就直接判定为同时满足限制条件1和2并continue。
对于判断是否满足限制条件1,可以使用统计的方法,即统计与每个点相连的每种颜色的边有几条,如果节点u和v中至少有一个点相连的颜色为w的边数等于2,那么限制条件1不满足。
对于限制条件2,直接判断在颜色w对应的LCT中,是否FindRoot(u)==FindRoot(v),如果是则限制条件2不满足。
如果同时满足限制条件1和2,则维护一下统计数组,然后在这条边原来的颜色对应的LCT中,执行Cut(u,v),再在颜色w对应的LCT中,执行Link(u,v)。
代码:
#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 = 1e4 + 5, M = 1e5 + 5; int n, m, fa[M], lc[M], rc[M], rev[M], len, que[M], c, Q, val[M], V[M], cnt [13], ecnt = 1, nxt[M << 1], adj[M], go[M << 1], col[M << 1]; void add_edge(int u, int v, int w) { nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v; col[ecnt] = w; } int tran(int x, int y) {return (x - 1) * c + 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 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 upt(int x) { val[x] = V[x]; if (lc[x]) val[x] = max(val[x], val[lc[x]]); if (rc[x]) val[x] = max(val[x], val[rc[x]]); } 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 val[y]; } int main() { int i, j, op, x, y, z; n = read(); m = read(); c = read(); Q = read(); for (i = 1; i <= n; i++) { x = read(); for (j = 1; j <= c; j++) { int p = tran(i, j); V[p] = val[p] = x; } } while (m--) { x = read(); y = read(); z = read() + 1; cnt[x][z]++; cnt[y][z]++; Link(tran(x, z), tran(y, z)); add_edge(x, y, z); add_edge(y, x, z); } while (Q--) { op = read(); x = read(); y = read(); if (op == 0) for (i = 1; i <= c; i++) z = tran(x, i), splay(z), V[z] = y, upt(z); else if (op == 1) { z = read() + 1; bool flag = 0; int co, ex; for (int e = adj[x]; e; e = nxt[e]) if (go[e] == y) {ex = e; co = col[e]; flag = 1; break;} if (!flag) {printf("No such edge.\n"); continue;} if (co == z) {printf("Success.\n"); continue;} if (cnt[x][z] == 2 || cnt[y][z] == 2) {printf("Error 1.\n"); continue;} if (Find_Root(tran(x, z)) == Find_Root(tran(y, z))) {printf("Error 2.\n"); continue;} printf("Success.\n"); Cut(tran(x, co), tran(y, co)); Link(tran(x, z), tran(y, z)); col[ex] = col[ex ^ 1] = z; cnt[x][co]--; cnt[y][co]--; cnt[x][z]++; cnt[y][z]++; } else { x++; z = read(); if (Find_Root(tran(y, x)) != Find_Root(tran(z, x))) {printf("-1\n"); continue;} else printf("%d\n", Select(tran(y, x), tran(z, x))); } } return 0; }
相关文章推荐
- bzoj2816 [ZJOI2012]网络(lct)
- BZOJ.2816.[ZJOI2012]网络(LCT)
- 【bzoj2816】【ZJOI2012】【网络】【lct】
- [ZJOI2012][bzoj 2816] 网络 network [LCT]
- [BZOJ2816][ZJOI2012]网络(LCT)
- [bzoj2816][ZJOI2012]网络(LCT,splay)
- [BZOJ2816][ZJOI2012]网络(lct+map)
- 【bzoj2816】[ZJOI2012]网络 LCT
- bzoj2816.。。。。zjoi2012网络
- BZOJ 2816 [ZJOI2012]网络
- AC日记——[ZJOI2012]网络 bzoj 2816
- BZOJ 2816 [ZJOI2012]网络 Link Cut Tree
- bzoj2816 [ZJOI2012]网络
- BZOJ2816:[ZJOI2012]网络——题解
- bzoj 2816: [ZJOI2012]网络(splay)
- bzoj2816 [ZJOI2012]网络
- [BZOJ2816][ZJOI2012]网络-Link Cut Tree
- bzoj千题计划223:bzoj2816: [ZJOI2012]网络
- 【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)
- [bzoj2816][ZJOI2012]网络