Description
Input
Output
Sample Input
4 5
1 2
2 3
3 4
4 1
2 4
3
1 5
2 2 3
2 1 2
Sample Output
Connected
Disconnected
Connected
HINT
N<=100000 M<=200000 K<=100000
分析:
对于询问建一棵线段树,每个节点开一个vector记录这些询问需要的边。
然后线段树分治。
一开始先把所有询问都不需要的边插入并查集。
然后询问左儿子时,把右儿子询问边但不是左儿子的询问边插入并查集,然后分治左儿子,做完后撤回。
右儿子同理。
判断是否连通只需要判断当前的集合大小是否为n。
代码:
/**************************************************************
Problem: 3237
User: ypxrain
Language: C++
Result: Accepted
Time:10724 ms
Memory:51212 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
const int maxn=2e5+7;
using namespace std;
int n,m,T,cnt;
int a[maxn][5],ans[maxn],p[maxn],size[maxn],h[maxn][2];
bool b[maxn];
struct edge{
int x,y;
}g[maxn];
vector <int> t[maxn*4];
int find(int x)
{
if (!p[x]) return x;
return find(p[x]);
}
void uni(int x,int y)
{
int u=find(x),v=find(y);
if (u==v) return;
if (size[u]>size[v]) swap(u,v);
p[u]=v;
size[v]+=size[u];
h[++cnt][0]=u;
h[cnt][1]=v;
}
void cut(int x,int y)
{
p[x]=0;
size[y]-=size[x];
}
void build(int p,int l,int r)
{
if (l==r)
{
for (int i=1;i<=a[l][0];i++) t[p].push_back(a[l][i]);
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
for (int i=0;i<t[p*2].size();i++)
{
int x=t[p*2][i];
b[x]=1;
t[p].push_back(x);
}
for (int i=0;i<t[p*2+1].size();i++)
{
int x=t[p*2+1][i];
if (!b[x]) t[p].push_back(x);
}
for (int i=0;i<t[p*2].size();i++)
{
int x=t[p*2][i];
b[x]=0;
}
}
void solve(int p,int l,int r)
{
if (l==r)
{
int c=find(1);
if (size[c]==n) ans[l]=1;
else ans[l]=0;
return;
}
int mid=(l+r)/2;
for (int i=0;i<t[p*2].size();i++)
{
int x=t[p*2][i];
b[x]=1;
}
int now=cnt;
for (int i=0;i<t[p*2+1].size();i++)
{
int x=t[p*2+1][i];
if (!b[x]) uni(g[x].x,g[x].y);
}
for (int i=0;i<t[p*2].size();i++)
{
int x=t[p*2][i];
b[x]=0;
}
solve(p*2,l,mid);
for (int i=cnt;i>now;i--) cut(h[i][0],h[i][1]);
cnt=now;
for (int i=0;i<t[p*2+1].size();i++)
{
int x=t[p*2+1][i];
b[x]=1;
}
for (int i=0;i<t[p*2].size();i++)
{
int x=t[p*2][i];
if (!b[x]) uni(g[x].x,g[x].y);
}
for (int i=0;i<t[p*2+1].size();i++)
{
int x=t[p*2+1][i];
b[x]=0;
}
solve(p*2+1,mid+1,r);
for (int i=cnt;i>now;i--) cut(h[i][0],h[i][1]);
cnt=now;
}
void prework()
{
for (int i=1;i<=n;i++) size[i]=1;
for (int i=0;i<t[1].size();i++)
{
int x=t[1][i];
b[x]=1;
}
for (int i=1;i<=m;i++)
{
if (!b[i]) uni(g[i].x,g[i].y);
else b[i]=0;
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d%d",&g[i].x,&g[i].y);
scanf("%d",&T);
for (int i=1;i<=T;i++)
{
scanf("%d",&a[i][0]);
for (int j=1;j<=a[i][0];j++) scanf("%d",&a[i][j]);
}
build(1,1,T);
prework();
solve(1,1,T);
for (int i=1;i<=T;i++)
{
if (ans[i]) printf("Connected\n");
else printf("Disconnected\n");
}
}