무향 그래프 주어 \ (Q \) 질의를 시간 후마다 유니콤도 여부, 원본 이미지의 에지를 제거하고자 양쪽 문의 주어진 수.
\ (N- \ Q \ ^ leq10. 5 \ m \ leq2 \ times10. ^ 5 \) , 챌린지 당 변의 개수 \ (\ leq4 \)
CDQ 분할 및 분리 된 세트 정복, 분할 정복
사실,이 엄격 CDQ 파티션을 간주 될 수 없습니다 ......
부분 및 최적화의 복잡성 사이의 메시지 중복 계산을 극대화하기 위해 고려되어야한다
격벽에 의해 시간 심문을 고려 현재 간격 \ ([L \의 R & LT] \) , 이들 가장자리 문의 제거 이산 블록 세트와의 통신을 유지 한 후에
다른 쪽 단부 측이 더 추가하도록, 이산 세트를 다른 쪽의 기부 재귀 일측 소거되지 전에 중복은 빈의 배열로 구현 될 수있다
그리고 \ ([1,5 \ 미드] \ [중간 + 1 \ r은] \) 끊긴 세트를 공유 할 수있다, 처리 \ ([L은 \ 미드] \) 이면 후에 취소 할 (\을 [1,5 \ R] \) 상태를 재 처리 (\ [MID +. 1 \의 R & LT] \) . 각 작업은 한 번만 취소됩니다, 그래서 시간 복잡도이 보장되기 때문에
시간 복잡도 \ (O (\ displaystyle \ 합 q 개의 \ 로그 \ 합 Q) \)
코드 (열 C ++ 11)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
bool ans[maxn];
int n, m, q, k;
struct edge {
int u, v;
} e[maxn << 1];
vector <int> Q[maxn];
#define nc getchar()
inline int read() {
int x = 0;
char c = nc;
while (c < 48) c = nc;
while (c > 47) x = (x << 3) + (x << 1) + (c ^ 48), c = nc;
return x;
}
#undef nc
// ---
bool vis[maxn << 1];
int now, T[maxn << 1];
inline void clr() { ++now; }
inline void upd(int pos) {
T[pos] = now, vis[pos] = 1;
}
inline bool query(int pos) {
return T[pos] < now ? 0 : vis[pos];
}
// array with clear
int par[maxn], sz[maxn];
int tot, top, st[maxn], bl[maxn];
inline int find(int x) {
while (par[x] != x) x = par[x];
return x;
}
inline void unite(int x, int y) {
if ((x = find(x)) != (y = find(y))) {
if (sz[x] < sz[y]) swap(x, y);
--tot;
par[y] = x, sz[x] += sz[y];
st[++top] = y, bl[top] = k;
}
}
inline void revert() {
for (; bl[top] >= k; --top, ++tot) {
int u = st[top];
sz[par[u]] -= sz[u], par[u] = u;
}
}
// union set
void cdq(int l, int r) {
if (l == r) {
ans[l] = tot == 1; return;
}
int mid = (l + r) >> 1;
for (int i = l; i <= mid; ++i) {
for (int p : Q[i]) upd(p);
}
for (int i = mid + 1; i <= r; ++i) {
for (int p : Q[i]) {
if (!query(p)) unite(e[p].u, e[p].v);
}
}
clr();
k <<= 1, cdq(l, mid), k >>= 1;
revert();
for (int i = mid + 1; i <= r; ++i) {
for (int p : Q[i]) upd(p);
}
for (int i = l; i <= mid; ++i) {
for (int p : Q[i]) {
if (!query(p)) unite(e[p].u, e[p].v);
}
}
clr();
k = k << 1 | 1, cdq(mid + 1, r), k >>= 1;
revert();
}
int main() {
n = read(), m = read();
for (int i = 1; i <= m; ++i) {
e[i].u = read(), e[i].v = read();
}
q = read();
for (int i = 1; i <= q; ++i) {
int k = read(), x;
while (k--) {
x = read();
Q[i].push_back(x), upd(x);
}
}
tot = n;
for (int i = 1; i <= n; ++i) {
par[i] = i, sz[i] = 1;
}
for (int i = 1; i <= m; ++i) {
if (!query(i)) unite(e[i].u, e[i].v);
}
clr(), k = 1, cdq(1, q);
for (int i = 1; i <= q; ++i) {
puts(ans[i] ? "Connected" : "Disconnected");
}
return 0;
}