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  阅读(...)  评论(...编辑  收藏

导航