题目大意:
给你一个01串,长度为N(N<=200),每一位不但能控制自己,还可以控制别的一些位,现在有反转操作,假设我们对第i位执行反转操作,那么i所控制的所有位都会反转。现在给你每位控制的集合,和初始01串,问是否存在一种操作方式使得这个串都为0或1。
解题思路:
直接高斯消元就行了。
没什么可说的。
AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
int fc_[300][300]={{0}};
int fc[300][300]={{0}};
int prt[300]={0};
int N;
bool Gauss()
{
memcpy(fc,fc_,sizeof(fc));
int remain=1;
for(int cnt=1;cnt<=N && remain<=N;cnt++)
{
int g;
for(g=remain;g<=N;g++)
{
if(fc[g][cnt]!=0)
break;
}
if(g==N+1) continue;
for(int i=0;i<=N;i++)
swap(fc[g][i],fc[remain][i]);
for(int i=1;i<=N;i++)
{
if(i==remain || fc[i][cnt]==0) continue;
for(int j=0;j<=N;j++)
fc[i][j]^=fc[remain][j];
}
remain++;
}
for(int i=remain;i<=N;i++)
if(fc[i][0]==1)
return false;
int ans=0;
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
if(fc[i][j]==1 && fc[i][0]==1)
{
ans++;
prt[j]=1;
break;
}
}
}
printf("%d\n",ans);
for(int i=1;i<=N;i++)
if(prt[i]==1)
printf("%d ",i);
printf("\n");
return true;
}
int main()
{
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
int j;
scanf("%d",&j);
for(;j>0;j--)
{
int p;
scanf("%d",&p);
fc_[p][i]=1;
}
}
for(int i=1;i<=N;i++)
scanf("%d",&fc_[i][0]);
if(Gauss())
return 0;
for(int i=1;i<=N;i++)
fc_[i][0]^=1;
if(Gauss())
return 0;
printf("-1\n");
return 0;
}
时间: 2024-10-19 01:07:46