CF1466 F. Euclid's nightmare

Problem - F - Codeforces

 

题意:

有n个不一样的m维向量,每个维度要么是0,要么是1,而且至多有2个维度是1

问这些向量取任意个在模2意义下相加,能得出多少种不同的向量

并找到一个个数最少且字典序最小的小向量集,里面的向量按上述相加可以得出答案的所有向量

 

加一个虚拟节点

若向量在第x维和第y维是1,x和y之间连边

若向量只在第x维是1,虚拟节点和x之间连边

在连边过程中,如果加入一条边出现了环,那么这个向量是无效的

因为环上的点每个点都会被累加2次,模2都是0

按输入顺序一个向量一个向量的加就可以了

 

#include<bits/stdc++.h>

using namespace std;

#define N 500003

int fa[N];
bool vis[N];
bool use[N];

const int mod=1e9+7;

int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); } 

int unionn(int x,int y)
{
    int fx=find(x),fy=find(y);
    if(fx==fy) return 1;
    fa[fx]=fy;
    return 0;
}

int poww(int b)
{
    int a=2,c=1;
    for(;b;a=1ll*a*a%mod,b>>=1)
        if(b&1) c=1ll*c*a%mod;
    return c;
}

int main()
{
    int n,m,k,x,y;
    int cnt=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i) fa[i]=i;
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&k);
        if(!k) continue;
        y=0;
        if(k==1) scanf("%d",&x);
        else if(k==2) scanf("%d%d",&x,&y);
        if(unionn(x,y)) ++cnt;
        else use[i]=true;
    }
    printf("%d %d\n",poww(n-cnt),n-cnt);
    for(int i=1;i<=n;++i)
        if(use[i]) printf("%d ",i);
}

 

posted @ 2021-10-19 20:14  TRTTG  阅读(67)  评论(0编辑  收藏  举报