CF1466 F. Euclid's nightmare
题意:
有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); }