bzoj 3569 DZY Loves Chinese II

bzoj

对于这题先套路的找出一棵生成树,然后还会剩下一些非树边,要删边使得图不连通(假设先删非树边)当且仅当删掉了一条没有返祖边覆盖的树边,或者是删了两条被相同的非树边集合覆盖的树边

现在要处理这个问题.我们给所有非树边一个随机权值,然后树边的权值就是覆盖它的非树边权值异或和,这个可以树上差分实现,那么两条树边如果异或和相等就认为覆盖它们的非树边集合相同,如果一条树边异或和为0就认为没有被覆盖.如果我们的随机的值域为\(2^w\),那么出错的概率就是\(\frac{1}{2^w}\),因为一个数只有正好选中一个对应的数才会出错

先给结论.对于给出的一个边集,删掉以后不连通,当且仅当这个边集中有一个子集权值异或和为0.接下来是感性证明:如果这个子集全是非树边那应该就在别的地方直接WA了;如果有一个是树边,也就是选出来的其他非树边都是覆盖它的,所以删掉后会不连通;如果有\(\ge 2\)个树边,那么一定可以把其他非树边分别异或到树边上去,使得有两个树边异或和相同.顺便再推荐一波理性证明.所以实现可以用线性基,做到出现线性相关的子集就可以不连通

#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double

using namespace std;
const int N=1e5+10;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int to[N*10],nt[N*10],hd[N],tot=1;
void add(int x,int y)
{
    ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
    ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
int n,m,q,fa[N],de[N],sz[N],hs[N],top[N];
uLL a[N],w[N*5],bs[70];
bool vv[N*5];
void dfs1(int x)
{
    sz[x]=1;
    for(int i=hd[x];i;i=nt[i])
    {
        int y=to[i];
        if(de[y]) continue;
        vv[i>>1]=1;
        fa[y]=x,de[y]=de[x]+1,dfs1(y);
        sz[x]+=sz[y],hs[x]=sz[hs[x]]>sz[y]?hs[x]:y;
    }
}
void dfs2(int x)
{
    if(hs[x]) top[hs[x]]=top[x],dfs2(hs[x]);
    for(int i=hd[x];i;i=nt[i])
    {
        int y=to[i];
        if(!vv[i>>1]||y==fa[x]||y==hs[x]) continue;
        top[y]=y,dfs2(y);
    }
}
int glca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(de[top[x]]<de[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    return de[x]<de[y]?x:y;
}
void dfs3(int x)
{
    for(int i=hd[x];i;i=nt[i])
    {
        int y=to[i];
        if(!vv[i>>1]||y==fa[x]) continue;
        dfs3(y),a[x]^=a[y],w[i>>1]=a[y];
    }
}

int main()
{
    n=rd(),m=rd();
    for(int i=1;i<=m;++i) add(rd(),rd());
    de[1]=1,dfs1(1);
    top[1]=1,dfs2(1);
    for(int i=1;i<=m;++i)
        if(!vv[i])
        {
            w[i]=(1ull*rand()<<32)|1ull*rand();
            int x=to[i<<1],y=to[i<<1|1],lca=glca(x,y);
            if(y==lca) swap(x,y);
            a[x]^=w[i],a[y]^=w[i];
            if(x!=lca) a[lca]^=w[i];
        }
    dfs3(1);
    q=rd();
    int las=0;
    while(q--)
    {
        memset(bs,0,sizeof(bs));
        bool ok=0;
        int kk=rd();
        while(kk--)
        {
            uLL x=w[rd()^las];
            for(int i=64;~i;--i)
                if(x>>i&1)
                {
                    if(!bs[i]){bs[i]=x;break;}
                    x^=bs[i];
                    if(!x) break;
                }
            ok|=!x;
        }
        las+=!ok;
        puts(ok?"Disconnected":"Connected");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/smyjr/p/11614760.html