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;
}

posted on 2016-03-14 17:07  wuyuhan  阅读(557)  评论(0编辑  收藏  举报

导航