BZOJ 3563 DZY Loves Chinese(线性基)

来源:互联网 发布:网络用语ps是什么意思 编辑:程序博客网 时间:2024/05/29 14:31

Description

神校XJ之学霸兮,Dzy皇考曰JC

摄提贞于孟陬兮,惟庚寅Dzy以降。

Dzy既有此内美兮,又重之以修能。

遂降临于OI界,欲以神力而凌♂辱众生。

Dzy有一魞歄图,其上有N座祭坛,又有M条膴蠁边。

时而DzyWA而怒发冲冠,神力外溢,遂有K条膴蠁边灰飞烟灭。

而后俟其日A50题则又令其复原。(可视为立即复原)

然若有祭坛无法相互到达,Dzy之神力便会大减,于是欲知其是否连通。

Input

第一行N,M

接下来Mx,y:表示M条膴蠁边,依次编号

接下来一行Q

接下来Q行:

每行第一个数K而后K个编号c1~cK:表示K条边,编号为c1~cK

为了体现在线,K以及c1~cK均需异或之前回答为连通的个数

(N1e5,M5e5,Q5e4,1K15)

数据保证没有重边与自环

Output

对于每个询问输出:连通则为Connected,不连通则为Disconnected(不加引号)

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

Solution

先找到原图的一个生成树,给非树边随机边权,定义点权为以其为端点的非树边边权异或和,给树定向之后,树边的权值为其深度较深的端点点权,这样如果删去的边集中存在一个子集使得其权值异或和为0,则说明一条树边及其周围的非树边全部被删掉,由于边权是随机的所以出错率很小

Code

#include<cstdio>#include<cstring>#include<algorithm>#include<ctime>using namespace std;namespace fastIO {    #define BUF_SIZE 100000    //fread -> read    bool IOerror=0;    inline char nc()     {        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;        if(p1==pend)         {            p1=buf;            pend=buf+fread(buf,1,BUF_SIZE,stdin);            if(pend==p1)             {                IOerror=1;                return -1;            }        }        return *p1++;    }    inline bool blank(char ch)     {        return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';    }    inline void read(int &x)     {        char ch;        while(blank(ch=nc()));        if(IOerror)return;        for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');    }    #undef BUF_SIZE};using namespace fastIO;const int maxn=100005,maxm=500005;struct node{    int v,next;}edge[maxm*2];int n,m,q,res,vis[maxn],val[maxn],weight[maxm],tot,head[maxn],base[33];void add(int u,int v){    edge[++tot].v=v,edge[tot].next=head[u],head[u]=tot;}void dfs(int u,int fa){    vis[u]=res++;    for(int i=head[u];i;i=edge[i].next)    {        int v=edge[i].v;        if(v==fa)continue;        if(!vis[v])        {            dfs(v,u);            weight[i/2]=val[v];            val[u]^=val[v];        }        else if(vis[u]>vis[v])        {            weight[i/2]=rand()+1;            val[u]^=weight[i/2];            val[v]^=weight[i/2];        }    }}int main(){    srand(19971109);    read(n);read(m);//scanf("%d%d",&n,&m);    tot=res=1;    while(m--)    {        int u,v;        read(u);read(v);//scanf("%d%d",&u,&v);        add(u,v),add(v,u);    }    dfs(1,0);    int num=0;    read(q);//scanf("%d",&q);    while(q--)    {        int k,temp,flag=0;        read(k);//scanf("%d",&k);        k^=num;        memset(base,0,sizeof(base));        while(k--)        {            read(temp);//scanf("%d",&temp);            temp=weight[temp^num];            for(int i=30;i>=0;i--)                if(temp>>i&1)                {                    if(!base[i])                    {                        base[i]=temp;                        break;                    }                    else temp^=base[i];                }             if(!temp)flag=1;        }        if(flag)printf("Disconnected\n");        else printf("Connected\n"),num++;    }    return 0;}