您的位置:首页 > 其它

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