您的位置:首页 > 理论基础 > 计算机网络

[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)。

代码:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: