LCT 常用模板

动态维护链上信息

例题:P3690 【模板】Link Cut Tree(动态树)

#include <bits/stdc++.h>
#define DEBUG fprintf(stderr, "Passing [%s] line %d
", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)

using namespace std;

typedef long long LL;
typedef pair <int, int> PII;
typedef pair <int, PII> 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
", 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 <bits/stdc++.h>
#define DEBUG fprintf(stderr, "Passing [%s] line %d
", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)

using namespace std;

typedef long long LL;
typedef pair <int, int> PII;
typedef pair <int, PII> 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 <bits/stdc++.h>
#define DEBUG fprintf(stderr, "Passing [%s] line %d
", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)

using namespace std;

typedef long long LL;
typedef pair <int, int> PII;
typedef pair <int, PII> 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
", ans[i]);
	return 0;
}

例题:[NOI2014]魔法森林

#include <bits/stdc++.h>
#define DEBUG fprintf(stderr, "Passing [%s] line %d
", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)

using namespace std;

typedef long long LL;
typedef pair <int, int> PII;
typedef pair <int, PII> 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
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/xsl19/p/13513663.html