神奇配方[VIJOS1221]

来源:互联网 发布:澳洲读高中 知乎 编辑:程序博客网 时间:2024/03/29 14:18

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; }


1 0
原创粉丝点击