BZOJ-3237: [Ahoi2013]连通图
BZOJ-3237: [Ahoi2013]连通图
标签(空格分隔): OI-BZOJ OI-整体二分 OI-并查集
Time Limit: 20 Sec
Memory Limit: 512 MB
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
Solution####
这图上数据范围不对坑爹呢。。。
整体二分。对询问二分。求询问[l,l]的答案的时候,需要把未在[l,l]间
出现的边缩成一个强联通分量,判断询问l的边是否在一个强联通分量。
在整体二分中处理方法为:对于当前区间[l,r],把在[mid+1,r]出现且
未在[l,mid]中出现的边缩起来,对[l,mid]递归处理;同理,把在[l,mid]
出现且未在[mid+1,r]中出现的边缩起来,对[mid+1,r]递归处理。
开始的时候把未被询问到的边缩起来。
Code####
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define PA pair<int,int>
int read()
{
int s=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*f;
}
//smile please
int n,m,Q;
int u[200005],v[200005];
struct que
{
int N,h;
int e[5];
}q[200005];
bool ans[200005];
int f[100005],s1[5000005],top=1;
int gf(int x)
{
if(f[x]==x)return x;
s1[top++]=x;s1[top++]=f[x];
return f[x]=gf(f[x]);
}
int p[200005],dd;
void mer(int u,int v)
{
if(gf(u)!=gf(v))
{s1[top++]=f[v];s1[top++]=f[f[v]];
f[f[v]]=f[u];
}
}
void solve(int l,int r)
{
int time=top,mid=l+r>>1;
if(l==r)
{int p=1;
for(int j=q[l].N,*k=q[l].e;j&&p;j--,k++)
if(gf(u[*k])!=gf(v[*k]))
p=0;
ans[q[l].h]=p;
while(top!=time)
f[s1[top-2]]=s1[top-1],top-=2;
return;
}
dd++;
for(int i=l;i<=mid;i++)
for(int j=q[i].N,*k=q[i].e;j;j--,k++)
p[*k]=dd;
for(int i=mid+1;i<=r;i++)
for(int j=q[i].N,*k=q[i].e;j;j--,k++)
if(p[*k]!=dd)
mer(u[*k],v[*k]);
solve(l,mid);
while(top!=time)
f[s1[top-2]]=s1[top-1],top-=2;
dd++;
for(int i=mid+1;i<=r;i++)
for(int j=q[i].N,*k=q[i].e;j;j--,k++)
p[*k]=dd;
for(int i=l;i<=mid;i++)
for(int j=q[i].N,*k=q[i].e;j;j--,k++)
if(p[*k]!=dd)
mer(u[*k],v[*k]);
solve(mid+1,r);
while(top!=time)
f[s1[top-2]]=s1[top-1],top-=2;
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n=read(),m=read();
for(int i=1;i<=m;i++)
u[i]=read(),v[i]=read();
for(int i=1;i<=n;i++)
f[i]=i;
Q=read();
for(int i=1;i<=Q;i++)
{q[i].N=read();q[i].h=i;
for(int j=0;j<q[i].N;j++)
q[i].e[j]=read();
}
dd++;
for(int i=1;i<=Q;i++)
for(int j=q[i].N,*k=q[i].e;j;j--,k++)
p[*k]=dd;
for(int i=1;i<=m;i++)
if(p[i]!=dd)
mer(u[i],v[i]);
solve(1,Q);
for(int i=1;i<=Q;i++)
puts(ans[i]?"Connected":"Disconnected");
//fclose(stdin);
//fclose(stdout);
return 0;
}