动态维护链上信息
例题:P3690 【模板】Link Cut Tree(动态树)
#include
#define DEBUG fprintf(stderr, "Passing [%s] line %d\n", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
using namespace std;
typedef long long LL;
typedef pair PII;
typedef pair PIII;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}
const int INF = 0x3f3f3f3f, N = 100003, M = N << 1;
int n, m;
int fa[N], c[N][2], v[N], s[N], stk[N];
bool r[N];
inline bool isroot(int x) {return c[fa[x]][0] == x || c[fa[x]][1] == x;}
inline void pushup(int x) {s[x] = s[c[x][0]] ^ s[c[x][1]] ^ v[x];}
inline void pushr(int x) {swap(c[x][0], c[x][1]), r[x] ^= 1;}
inline void pushdown(int x)
{
if (r[x])
{
if (c[x][0]) pushr(c[x][0]);
if (c[x][1]) pushr(c[x][1]);
r[x] = 0;
}
}
inline void rotate(int x)
{
int y = fa[x], z = fa[y], k = (c[y][1] == x), w = c[x][!k];
if (isroot(y)) c[z][c[z][1] == y] = x;
c[x][!k] = y, c[y][k] = w;
if (w) fa[w] = y;
fa[x] = z, fa[y] = x;
pushup(y);
}
inline void splay(int x)
{
int y = x, z = 0;
stk[z = 1] = y;
while (isroot(y)) stk[++z] = y = fa[y];
while (z) pushdown(stk[z--]);
while (isroot(x))
{
y = fa[x], z = fa[y];
if (isroot(y))
rotate(((c[z][1] == y) ^ (c[y][1] == x)) ? x : y);
rotate(x);
}
pushup(x);
}
inline void access(int x)
{
for (int y = 0; x; x = fa[y = x])
splay(x), c[x][1] = y, pushup(x);
}
inline void makeroot(int x)
{
access(x); splay(x);
pushr(x);
}
inline int findroot(int x)
{
access(x); splay(x);
while (c[x][0]) pushdown(x), x = c[x][0];
splay(x);
return x;
}
inline void split(int x, int y)
{
makeroot(x);
access(y);
splay(y);
}
inline void link(int x, int y)
{
makeroot(x);
if (findroot(y) != x) fa[x] = y;
}
inline void cut(int x, int y)
{
makeroot(x);
if (findroot(y) == x && fa[y] == x && !c[y][0])
{
fa[y] = c[x][1] = 0;
pushup(x);
}
}
int main()
{
//File("");
n = gi(), m = gi();
for (int i = 1; i <= n; i+=1) v[i] = gi();
while (m--)
{
int op = gi(), x = gi(), y = gi();
if (op == 0) split(x, y), printf("%d\n", s[y]);
else if (op == 1) link(x, y);
else if (op == 2) cut(x, y);
else splay(x), v[x] = y;
}
return 0;
}
动态维护连通性
例题:[SDOI2008]洞穴勘测
#include
#define DEBUG fprintf(stderr, "Passing [%s] line %d\n", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
using namespace std;
typedef long long LL;
typedef pair PII;
typedef pair PIII;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}
const int INF = 0x3f3f3f3f, N = 10003, M = N << 1;
int n, m;
int fa[N], stk[N], c[N][2];
bool r[N];
inline bool isroot(int x) {return c[fa[x]][0] == x || c[fa[x]][1] == x;}
inline void pushr(int x) {swap(c[x][0], c[x][1]); r[x] ^= 1;}
inline void pushdown(int x)
{
if (r[x])
{
if (c[x][0]) pushr(c[x][0]);
if (c[x][1]) pushr(c[x][1]);
r[x] = 0;
}
}
inline void rotate(int x)
{
int y = fa[x], z = fa[y], k = (c[y][1] == x), w = c[x][!k];
if (isroot(y)) c[z][c[z][1] == y] = x;
c[x][!k] = y, c[y][k] = w;
if (w) fa[w] = y;
fa[x] = z, fa[y] = x;
}
inline void splay(int x)
{
int y = x, z = 0;
stk[z = 1] = y;
while (isroot(y)) stk[++z] = y = fa[y];
while (z) pushdown(stk[z--]);
while (isroot(x))
{
y = fa[x], z = fa[y];
if (isroot(y))
rotate(((c[z][1] == y) ^ (c[y][1] == x)) ? x : y);
rotate(x);
}
}
inline void access(int x)
{
for (int y = 0; x; x = fa[y = x])
splay(x), c[x][1] = y;
}
inline void makeroot(int x)
{
access(x); splay(x);
pushr(x);
}
inline int findroot(int x)
{
access(x); splay(x);
while (c[x][0]) pushdown(x), x = c[x][0];
splay(x);
return x;
}
inline void link(int x, int y)
{
makeroot(x);
if (findroot(y) != x) fa[x] = y;
}
inline void cut(int x, int y)
{
makeroot(x);
if (findroot(y) == x && fa[y] == x && !c[y][0])
{
fa[y] = c[x][1] = 0;
}
}
int main()
{
//File("");
n = gi(), m = gi();
while (m--)
{
char s[9];
scanf("%s", s);
int x = gi(), y = gi();
if (s[0] == 'C') link(x, y);
else if (s[0] == 'D') cut(x, y);
else
{
if (findroot(x) == findroot(y)) puts("Yes");
else puts("No");
}
}
return 0;
}
动态维护最小生成树
例题:[WC2006]水管局长
反过来操作,把删边变成加边。
#include
#define DEBUG fprintf(stderr, "Passing [%s] line %d\n", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
using namespace std;
typedef long long LL;
typedef pair PII;
typedef pair PIII;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}
const int INF = 0x3f3f3f3f, N = 1003, M = 200003, S = N + M;
int n, m, q;
struct Node
{
int u, v, w;
} a[S];
struct Query
{
int op, u, v;
} b[M];
int fa[S], c[S][2], val[S], id[S], stk[S], fat[S];
bool r[S];
inline bool cmp(Node x, Node y) {return x.w < y.w;}
int getf(int u)
{
if (fat[u] == u) return u;
return fat[u] = getf(fat[u]);
}
inline void unionn(int u, int v)
{
int fu = getf(u), fv = getf(v);
if (fu != fv) fat[fu] = fat[fv];
}
inline bool isroot(int x) {return c[fa[x]][0] == x || c[fa[x]][1] == x;}
inline void pushr(int x) {swap(c[x][0], c[x][1]), r[x] ^= 1;}
inline void pushup(int x)
{
id[x] = x;
if (c[x][0] && val[id[x]] < val[id[c[x][0]]]) id[x] = id[c[x][0]];
if (c[x][1] && val[id[x]] < val[id[c[x][1]]]) id[x] = id[c[x][1]];
}
inline void pushdown(int x)
{
if (r[x])
{
if (c[x][0]) pushr(c[x][0]);
if (c[x][1]) pushr(c[x][1]);
r[x] = 0;
}
}
inline void rotate(int x)
{
int y = fa[x], z = fa[y], k = (c[y][1] == x), w = c[x][!k];
if (isroot(y)) c[z][c[z][1] == y] = x;
c[x][!k] = y, c[y][k] = w;
if (w) fa[w] = y;
fa[x] = z, fa[y] = x;
pushup(y);
}
inline void splay(int x)
{
int y = x, z = 0;
stk[z = 1] = y;
while (isroot(y)) stk[++z] = y = fa[y];
while (z) pushdown(stk[z--]);
while (isroot(x))
{
y = fa[x], z = fa[y];
if (isroot(y))
rotate(((c[z][1] == y) ^ (c[y][1] == x)) ? x : y);
rotate(x);
}
pushup(x);
}
inline void access(int x)
{
for (int y = 0; x; x = fa[y = x])
splay(x), c[x][1] = y, pushup(x);
}
inline void makeroot(int x)
{
access(x); splay(x);
pushr(x);
}
inline int findroot(int x)
{
access(x); splay(x);
while (c[x][0]) pushdown(x), x = c[x][0];
splay(x);
return x;
}
inline void split(int x, int y)
{
makeroot(x);
access(y);
splay(y);
}
inline void link(int x, int y)
{
makeroot(x);
if (findroot(y) != x) fa[x] = y;
}
inline void cut(int x, int y)
{
makeroot(x);
if (findroot(y) == x && fa[y] == x && !c[y][0])
{
fa[y] = c[x][1] = 0;
pushup(x);
}
}
bool del[N][N];
int z[N][N], kk[N][N];
int ans[M];
int main()
{
n = gi(), m = gi(), q = gi();
for (int i = 1; i <= m; i+=1)
{
int u = gi(), v = gi(), t = gi();
a[i] = (Node){u, v, t};
}
sort(a + 1, a + 1 + m, cmp);
for (int i = 1; i <= m; i+=1)
{
val[i + n] = a[i].w;
int u = a[i].u, v = a[i].v;
z[u][v] = z[v][u] = a[i].w;
kk[u][v] = kk[v][u] = i;
}
for (int i = 1; i <= n + m; i+=1) id[i] = fat[i] = i;
for (int i = 1; i <= q; i+=1)
{
int op = gi(), u = gi(), v = gi();
b[i] = (Query){op, u, v};
if (op == 2) del[u][v] = del[v][u] = true;
}
for (int i = 1; i <= m; i+=1)
{
if (del[a[i].u][a[i].v]) continue;
int fx = getf(a[i].u), fy = getf(a[i].v);
if (fx != fy)
unionn(fx, fy), link(i + n, a[i].u), link(i + n, a[i].v);
else
{
split(a[i].u, a[i].v);
int mx = id[a[i].v];
if (a[i].w < val[mx])
cut(mx, a[mx - n].u), cut(mx, a[mx - n].v),
link(i + n, a[i].u), link(i + n, a[i].v);
}
}
for (int i = q; i >= 1; i-=1)
if (b[i].op == 1)
{
split(b[i].u, b[i].v);
ans[i] = val[id[b[i].v]];
}
else
{
int fx = getf(b[i].u), fy = getf(b[i].v);
if (fx != fy)
unionn(fx, fy), link(kk[b[i].u][b[i].v] + n, b[i].u), link(kk[b[i].u][b[i].v] + n, b[i].v);
else
{
split(b[i].u, b[i].v);
int mx = id[b[i].v];
if (z[b[i].u][b[i].v] < val[mx])
cut(mx, a[mx - n].u), cut(mx, a[mx - n].v),
link(kk[b[i].u][b[i].v] + n, b[i].u), link(kk[b[i].u][b[i].v] + n, b[i].v);
}
}
for (int i = 1; i <= q; i+=1)
if (b[i].op == 1) printf("%d\n", ans[i]);
return 0;
}
例题:[NOI2014]魔法森林
#include
#define DEBUG fprintf(stderr, "Passing [%s] line %d\n", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
using namespace std;
typedef long long LL;
typedef pair PII;
typedef pair PIII;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}
const int INF = 0x3f3f3f3f, N = 50003, M = N << 1, S = N + M;
int n, m;
int fa[S], c[S][2], mn[S], stk[S], val[S], id[S], fat[S];
int tot;
bool r[S];
int ans = INF;
struct Node
{
int x, y, a, b;
} a[S];
int getf(int x)
{
if (fat[x] == x) return x;
return fat[x] = getf(fat[x]);
}
inline void unionn(int x, int y)
{
int ux = getf(x), uy = getf(y);
fat[ux] = uy;
}
inline bool cmp(Node x, Node y)
{
if (x.a != y.a) return x.a < y.a;
return x.b < y.b;
}
inline bool isroot(int x) {return c[fa[x]][0] == x || c[fa[x]][1] == x;}
inline void pushr(int x) {swap(c[x][1], c[x][0]), r[x] ^= 1;}
inline void pushup(int x)
{
id[x] = x;
if (c[x][0] && val[id[x]] < val[id[c[x][0]]]) id[x] = id[c[x][0]];
if (c[x][1] && val[id[x]] < val[id[c[x][1]]]) id[x] = id[c[x][1]];
}
inline void pushdown(int x)
{
if (r[x])
{
if (c[x][0]) pushr(c[x][0]);
if (c[x][1]) pushr(c[x][1]);
r[x] = 0;
}
}
inline void rotate(int x)
{
int y = fa[x], z = fa[y], k = (c[y][1] == x), w = c[x][!k];
if (isroot(y)) c[z][c[z][1] == y] = x;
c[y][k] = w, c[x][!k] = y;
if (w) fa[w] = y;
fa[x] = z, fa[y] = x;
pushup(y);
}
inline void splay(int x)
{
int y = x, z = 0;
stk[z = 1] = y;
while (isroot(y)) stk[++z] = y = fa[y];
while (z) pushdown(stk[z--]);
while (isroot(x))
{
y = fa[x], z = fa[y];
if (isroot(y))
rotate(((c[z][1] == y) ^ (c[y][1] == x)) ? x : y);
rotate(x);
}
pushup(x);
}
inline void access(int x)
{
for (int y = 0; x; x = fa[y = x])
splay(x), c[x][1] = y, pushup(x);
}
inline void makeroot(int x)
{
access(x); splay(x);
pushr(x);
}
inline int findroot(int x)
{
access(x); splay(x);
while (c[x][0]) pushdown(x), x = c[x][0];
splay(x);
return x;
}
inline void split(int x, int y)
{
makeroot(x);
access(y);
splay(y);
}
inline void link(int x, int y)
{
makeroot(x);
if (findroot(y) != x) fa[x] = y;
}
inline void cut(int x, int y)
{
makeroot(x);
if (findroot(y) == x && fa[y] == x && !c[y][0])
{
fa[y] = c[x][1] = 0;
pushup(x);
}
}
int main()
{
//File("");
n = gi(), m = gi();
for (int i = 1; i <= m; i+=1)
{
int x = gi(), y = gi(), aa = gi(), b = gi();
if (x == y) continue;
a[++tot] = (Node){x, y, aa, b};
}
for (int i = 1; i <= n + tot; i+=1) fat[i] = id[i] = i;
sort(a + 1, a + 1 + tot, cmp);
for (int i = 1; i <= tot; i+=1) val[i + n] = a[i].b;
for (int i = 1; i <= tot; i+=1)
{
int fx = getf(a[i].x), fy = getf(a[i].y);
if (fx != fy) unionn(fx, fy), link(i + n, a[i].x), link(i + n, a[i].y);
else
{
split(a[i].x, a[i].y);
int mx = id[a[i].y];
if (a[i].b < val[mx])
cut(mx, a[mx - n].x), cut(mx, a[mx - n].y), link(i + n, a[i].x), link(i + n, a[i].y);
}
if (getf(1) == getf(n))
{
split(1, n);
ans = min(ans, a[i].a + val[id[n]]);
}
}
if (ans == INF) puts("-1");
else printf("%d\n", ans);
return 0;
}