BZOJ 3237 连通图(线性基)

来源:互联网 发布:阿里云域名解析不生效 编辑:程序博客网 时间:2024/06/03 21:08

Description

给定一个连通的无向图和若干小集合,每个小集合包含一些边。对于每个集合,你需要确定将集合中的边从原先的无向图中删除后该图是否保持连通。一个图是连通的当且仅当任意两个不同的点之间存在一条路径连接他们。

Input

输入的第一行包含两个整数nm(1n10000,1m100000),表示无向图的点数和边数,每个点从1n标号。接下来的m行表示图的每条边,每行包含两个整数ab——一条边连接的两个端点的标号。保证每对顶点最多被一条边连接。没有一条边连接两个相同的顶点。每条边按照输入的顺序标号为1m。接下来的一行包含一个整数k(1k100000),表示需要测试的小集合的个数。接下来的k行每行描述一个小集合。每行的第一个数c(1c4)表示集合中边的个数,接下来有c个整数表示集合中边的标号,保证集合中的整数互不相同、

Output

输出k行,每行对应一个小集合的测试结果。第i行包含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=200005;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);        memset(base,0,sizeof(base));        while(k--)        {            read(temp);//scanf("%d",&temp);            temp=weight[temp];            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;}
原创粉丝点击