BZOJ 3069 [LCT][并查集][双连通分量]
2017-04-10 14:33
323 查看
Description
Byteasar是一个很纠结的人。每次他经过Bytetown的时候都知道有至少2条不同的路径可以选择,这导致他必须花很长时间来决定走哪条路。Byteasar最近听说了Bytetown的修路计划,他可能是唯一一个为此感到高兴的人——他有机会消除他的烦恼。在Byteasar一共有n个岔口,连接着m条双向道路。两条路径完全不同当且仅当他们没有公共的道路(但是允许经过相同的岔口)。
Byteasar想知道:对于两个岔口x y,是否存在一对完全不同的路径。
Solution
%%%Claris可能是自己sb了。。。居然调了那么久,看来以后LCT必须要很熟练的写啊。。。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> using namespace std; const int N = 301010; const int INF = 1 << 30; inline char get(void) { static char buf[100000], *S = buf, *T = buf; if (S == T) { T = (S = buf) + fread(buf, 1, 100000, stdin); if (S == T) return EOF; } return *S++; } inline void read(int &x) { static char c; x = 0; for (c = get(); c < '0' || c > '9'; c = get()); for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0'; } inline void readopt(int &opt) { static char c; for (c = get(); c != 'Z' && c != 'P'; c = get()); opt = (c == 'Z'); } int n, m, q, Gcnt, x, y, z, cnt; int a , b ; int fa , rk ; int ans ; struct Qry { int opt, x, y, id; inline friend bool operator <(const Qry &a, const Qry &b) { return a.id > b.id; } }; Qry Q ; vector<int> e , g ; inline int Fa(int x) { return fa[x] == x ? x : fa[x] = Fa(fa[x]); } inline int Merge(int x, int y) { static int f1, f2; f1 = Fa(x); f2 = Fa(y); if (f1 == f2) return false; if (rk[f1] > rk[f2]) swap(f1, f2); if (rk[f1] == rk[f2]) rk[f2]++; fa[f1] = f2; return 1; } namespace LCT { int f ; bool br , st , sm ; int ch [2]; bool rev ; int sta ; inline bool IsRoot(int x) { return ch[f[x]][0] != x && ch[f[x]][1] != x; } inline void PushDown(int x) { if (rev[x]) { rev[ch[x][0]] ^= 1; rev[ch[x][1]] ^= 1; swap(ch[x][0], ch[x][1]); rev[x] = 0; } if (st[x]) { st[ch[x][0]] = st[ch[x][1]] = 1; br[ch[x][0]] = br[ch[x][1]] = 0; sm[ch[x][0]] = sm[ch[x][1]] = 0; st[x] = 0; } } inline void PushUp(int x) { sm[x] = br[x] | sm[ch[x][0]] | sm[ch[x][1]]; } inline void Rotate(int x) { int y = f[x], z = f[y], l = (ch[y][0] != x), r = l ^ 1; if (!IsRoot(y)) { if (ch[z][0] == y) ch[z][0] = x; else ch[z][1] = x; } f[x] = z; f[y] = x; f[ch[x][r]] = y; ch[y][l] = ch[x][r]; ch[x][r] = y; PushUp(y); PushUp(x); } void Splay(int x) { int top = 0; sta[++top] = x; for (int i = x; !IsRoot(i); i = f[i]) sta[++top] = f[i]; while (top) PushDown(sta[top--]); while (!IsRoot(x)) { int y = f[x], z = f[y]; if (!IsRoot(y)) { if (ch[y][0] == x ^ ch[z][0] == y) Rotate(x); else Rotate(y); } Rotate(x); } } void Access(int x) { for (int t = 0; x; x = f[x]) { Splay(x); ch[x][1] = t; PushUp(x); t = x; } } void MakeRoot(int x) { Access(x); Splay(x); rev[x] ^= 1; } void Link(int x, int y) { MakeRoot(x); f[x] = y; } void MakePath(int x, int y) { MakeRoot(x); Access(y); Splay(y); } void Cut(int x, int y) { MakePath(x, y); ch[y][0] = f[x] = 0; PushUp(y); } }; using namespace LCT; void AddEdge(int x, int y, int z) { if (Merge(x, y)) { Link(x, z); Link(y, z); br[z] = sm[z] = 1; } else { MakePath(x, y); st[y] = 1; sm[y] = br[y] = 0; } } int Query(int x, int y) { if (Fa(x) != Fa(y)) return 1; MakePath(x, y); return sm[y]; } int main(void) { read(n); read(m); read(q); cnt = n; for (int i = 1; i <= n; i++) { fa[i] = i; e[i].push_back(INF); } for (int i = 1; i <= m; i++) { read(x); read(y); if (x > y) swap(x, y); a[i] = x; b[i] = y; } for (int i = 1; i <= q; i++) { readopt(Q[i].opt); read(Q[i].x); read(Q[i].y); if (Q[i].x > Q[i].y) swap(Q[i].x, Q[i].y); if (Q[i].opt) e[Q[i].x].push_back(Q[i].y); } for (int i = 1; i <= n; i++) sort(e[i].begin(), e[i].end()); for (int i = 1; i <= m; i++) { if (*lower_bound(e[a[i]].begin(), e[a[i]].end(), b[i]) == b[i]) continue; AddEdge(a[i], b[i], ++cnt); } reverse(Q + 1, Q + q + 1); for (int i = 1; i <= q; i++) { if (Q[i].opt) AddEdge(Q[i].x, Q[i].y, ++cnt); else ans[i] = Query(Q[i].x, Q[i].y); } for (int i = q; i; i--) if (!Q[i].opt) printf(ans[i] ? "NIE\n" : "TAK\n"); return 0; }
相关文章推荐
- BZOJ 2959: 长跑 [lct 双连通分量 并查集]
- BZOJ-2049 2049: [Sdoi2008]Cave 洞穴勘测 LCT||并查集||可撤销并查集+时间分治
- 【BZOJ 1180】OTOCI【LCT】&【树链剖分+并查集】
- [BZOJ2959][清橙1379]长跑-LCT-并查集
- [BZOJ2049]SDOI2008洞穴勘测|LCT|并查集
- [CDQ分治 并查集 || LCT] BZOJ 4025 二分图
- BZOJ 4025|二分图|CDQ分治|并查集|LCT
- [ LCT 并查集 ] BZOJ4998
- 【LCT+并查集】BZOJ2959[长跑]题解
- [BZOJ2959]长跑 LCT+双联通分量+并查集
- [bzoj3669][Noi2014]魔法森林_LCT_并查集
- bzoj 1453 双面棋盘 LCT 并查集
- 【bzoj4551】[Tjoi2016&Heoi2016]树 并查集
- 【BZOJ】【3673】可持久化并查集 & 【3674】可持久化并查集加强版
- _bzoj1015 [JSOI2008]星球大战starwar【并查集】
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测——LCT
- bzoj 3296: [USACO2011 Open] Learning Languages(并查集)
- BZOJ 3211&3038 并查集+树状数组 解题报告
- bzoj 1015 正难则反+并查集
- bzoj2759:一个动态树好题 (LCT+Exgcd)