AC通道:https://vijos.org/p/1221
[分析]
因为一个村民对于他(她)回答的事件A、B,都说假话或都说真话,所以它们可以看作一个事件。将可以看做一个事件的几个事件合并起来,最后统计事件的个数k,则答案数就是2^k。至于是否有解,可以用设置虚拟节点的方法解决。如果某个村民说A与B的真假不相同,而另外的村民说A与B的真假相同,则这个问题无解
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct bign{
int num[100],len;
bign(int a=0){
memset(num,0,sizeof(num));
len=1;
num[len]=a;
}
bign operator = (const char *str){
len=strlen(str);
for(int i=1;i<=len;i++)num[i]=str[len-i]-'0';
return *this;
}
bign operator = (const int a){
char str[100];
sprintf(str,"%d",a);
*this=str;
return *this;
}
bign operator *=(const int a){
int b=0;
for(int i=1;i<=len+1;i++){
num[i]=num[i]*a+b;
b=num[i]/10;
if(num[i]>=10){
num[i]%=10;
}
}
if(num[len+1])len++;
return *this;
}
void print(){
for(int i=len;i>=1;i--)printf("%d",num[i]);
}
};
int n,m;
int fa[1000],answer;
bool ans[1000];
int find(int x){
int tmp=x,pre;
while(tmp!=fa[tmp])tmp=fa[tmp];
while(x!=tmp){
pre=fa[x];
fa[x]=tmp;
x=pre;
}
return tmp;
}
void merge(int x,int y){
int fx=find(x),fy=find(y);
fa[fx]=fy;
}
bign power(int a,int b){
bign ans=1;
for(int i=1;i<=b;i++){
ans*=2;
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n*2;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(b==d){
if(find(a)==find(c+n)||find(c)==find(a+n)){
printf("No Answer\n");
return 0;
}
merge(a,c);
merge(a+n,c+n);
}
if(b!=d){
if(find(a)==find(c)||find(a+n)==find(c+n)){
printf("No Answer\n");
return 0;
}
merge(a+n,c);
merge(a,c+n);
}
}
for(int i=1;i<=n*2;i++){ans[find(i)]=true;}
for(int i=1;i<=n*2;i++)answer+=ans[i];
power(2,(answer)/2).print();
return 0;
}