hdu 4115 石头剪子布(2-sat问题)

/*
题意:石头剪子布,现在已知n回合bob将会出什么,对alice有限制,对于u,v,w;如果w=0说明a,b回合必须出的一样
否则,必须不一样。alice如果输一回合就输了,否则就赢了
解:
2-sat
alice有两个选择要么平手要么赢。
对于第u回合,alice可以出au,bu;
对于第v回合,alice可以出av,bv;
当w=0那么第u回合和第v回合必须相同
比较au和bu。bv是否矛盾,如果矛盾建两条边
比较av和bu。bv是否矛盾,如果矛盾建两条边
当w=1第u回合和第v回合必须不相同
比较au和bu。bv是否矛盾,如果矛盾建两条边
比较av和bu。bv是否矛盾,如果矛盾建两条边
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define N 21000
#define NN 11000
struct node
{
    int u,v,next;
} bian[NN*20];
int head[N],yong,low[N],dfn[N],belong[N],ans,top,index,stac[N],vis[N];
void init()
{
    memset(head,-1,sizeof(head));
    yong=index=ans=top=0;
    memset(vis,0,sizeof(vis));
    memset(dfn,0,sizeof(dfn));
}
void addedge(int u,int v)
{
    bian[yong].v=v;
    bian[yong].next=head[u];
    head[u]=yong++;
}
void tarjan(int u)
{
    low[u]=dfn[u]=++index;
    stac[++top]=u;
    vis[u]=1;
    int i;
    for(i=head[u]; i!=-1; i=bian[i].next)
    {
        int v=bian[i].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        ans++;
        int t;
        do
        {
            t=stac[top--];
            belong[t]=ans;
            vis[t]=0;
        }
        while(t!=u);
    }
}
int slove(int n)
{
    int i;
    for(i=0; i<n*2; i++)
        if(!dfn[i])
            tarjan(i);
    // printf("%d\n",ans);
    for(i=0; i<n; i++)
        if(belong[i]==belong[i+n])
            return 0;
    return 1;
}
void Switch(int f,int &au,int &av)
{
    au=f;
    av=(f+1)%3;
    return ;
}
int a[N];
int main()
{
    int t,n,m,i,k=0,u,v,w;
    int au,av,bu,bv;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
            a[i]--;
        }
        init();
        for(i=0; i<m; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            u--;
            v--;
            Switch(a[u],au,av);
            Switch(a[v],bu,bv);
            if(!w)
            {
                if(au!=bu)
                {
                    addedge(u,v+n);
                    addedge(v,u+n);
                }
                if(au!=bv)
                {
                    addedge(u,v);
                    addedge(v+n,u+n);
                }
                if(av!=bu)
                {
                    addedge(u+n,v+n);
                    addedge(v,u);
                }
                if(av!=bv)
                {
                    addedge(u+n,v);
                    addedge(v+n,u);
                }
            }
            else
            {
                if(au==bu)
                {
                    addedge(u,v+n);
                    addedge(v,u+n);
                }
                if(au==bv)
                {
                    addedge(u,v);
                    addedge(v+n,u+n);
                }
                if(av==bu)
                {
                    addedge(u+n,v+n);
                    addedge(v,u);
                }
                if(av==bv)
                {
                    addedge(u+n,v);
                    addedge(v+n,u);
                }
            }
        }
        if(!slove(n))
            printf("Case #%d: no\n",++k);
        else
            printf("Case #%d: yes\n",++k);
    }
    return 0;
}

时间: 2024-12-20 03:43:34

hdu 4115 石头剪子布(2-sat问题)的相关文章

石头剪子布的研究价值

听"中国之声"的新闻点评,谈到"中国科研人员发现石头剪子布的必胜绝技"引起的争议.上网找到一个新闻转载"中国科学家:发现石头剪子布的必胜绝技",尤其是注意到后面的评论.写下此文,是深感公众(包括媒体人),该对"研究"二字有些基本的认识. 研究,是为了发现规律.发现规律,方能运用规律,将其作用于社会生活,以及开发产品中去.研究要针对问题,可以是大问题,也可以是小问题,甚至只是小问题中的一个方面.研究所针对的问题,不能够面面俱到,

【TK】1019: 石头剪子布

题目描述 现在有两个人在玩石头剪子布游戏,请你判断最后谁赢了.用R代表石头,S代表剪子,P代表布. 输入 输入的第一行是一个整数t(0<t<1000),表示测试样例的数目.每组输入样例的第一行是一个整数n(0<n<100),表示游戏次数.接下来n行,每行由两个字母组成,两个字母之间用一个空格分隔,这些字母只会是R,S或P.第一个字母表示Player1的选择,第二个字母表示Player2的选择. 输出 对于每组输入样例,输出获胜方的名字(Player1或Player2),如果平均,则

1-7-04:石头剪子布

描述 石头剪子布,是一种猜拳游戏.起源于中国,然后传到日本.朝鲜等地,随着亚欧贸易的不断发展它传到了欧洲,到了近现代逐渐风靡世界.简单明了的规则,使得石头剪子布没有任何规则漏洞可钻,单次玩法比拼运气,多回合玩法比拼心理博弈,使得石头剪子布这个古老的游戏同时用于"意外"与"技术"两种特性,深受世界人民喜爱. 游戏规则:石头打剪刀,布包石头,剪刀剪布. 现在,需要你写一个程序来判断石头剪子布游戏的结果. 输入输入包括N+1行:第一行是一个整数N,表示一共进行了N次游戏.

Java练习 SDUT-2733_小鑫の日常系列故事(二)——石头剪子布

小鑫の日常系列故事(二)--石头剪子布 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 小鑫在上幼儿园的时候,喜欢跟小伙伴健健玩石头剪子布的游戏 ,你能帮他们判断谁胜谁负么? Input 输入有两行,每一行都有可能为"Rock"(石头),"Scissors"(剪子),"Cloth"(布).第一行为小鑫的选择,第二行为健健的选择. Output 输出有一行,如果小鑫赢了

团队-游戏石头剪子布-需求分析

1 引言 1.1 编写目的 童年时期没有网络游戏,没有游戏机,只有一些随时随地都能玩的一些小游戏,例如<石头,剪刀,布>,制作这款游戏只为了怀念逝去的童年1.2 背景 小的时候没有什么高大上的电子游戏,平时只会和小伙伴一起玩一些类似石头剪刀布的小游戏,为了向我们已逝去的童年致敬,我们做了这款游戏 本项目的名称:小游戏<石头,剪刀,布> 本项目的提出者:王聪,李宇鸿 本项目的开发者:王聪,李宇鸿,余兴财,王佳傲,魏来,李佳旭 1.3 参考资料<第一行代码Android 第二版&

Wikioi 3776 生活大爆炸版石头剪子布

题目描述 Description 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负.在<生活大爆炸>第二季第8集中出现了一种石头剪刀布的升级版游戏.升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势: 斯波克:<星际迷航>主角之一. 蜥蜴人:<星际迷航>中的反面角色. 这五种手势的胜负关系如表一所示,表中列出的是甲对乙的游戏结果. 现在,小A和小B尝试玩这种升级版的猜拳游戏.已知他们的出拳都是有周期性规律的,但周期长度不

例题:石头剪子布。用数组做。比较难理解,主要是逻辑思维

Random r = new Random(); //随机定义两个人 string[] s1 = new string[] { "剪刀", "石头", "布" }; string[] s2 = new string[] { "剪刀", "石头", "布" }; //随机定义两个人的数组 string jg; while (true) { int sj1 = r.Next(0, 3); 

石头剪子布游戏

import random ops = {'s' : 2, 'j' : 1, 'b' : 0} while True: x = raw_input('you>') ss = random.randint(0, 2) for t in ops.iteritems(): if t[1] == ss: print 'pc:',t[0] rs = ops[x] - ss if rs == 1 or rs == -2: print 'win' elif rs == 0: print 'equal' els

IOS-石头剪子布小程序

今天忙里偷闲,写了个石头剪子布的小程序,给大家做个小参考 主要功能如图:1.未开始出拳时,双方不停的做动画,并伴随背景音乐. 2.出拳后,判断双方输赢,并给相应的一方加分,伴随相应音效. 3.点击继续按钮,重新开始游戏. 首先,在StroryBoard中,拖几个控件,包括:电脑的出拳ImageView,玩家出拳的ImageView,双方的得分label;玩家选择出拳对象的button:承载button的View:然后在.h文件中  进行连线. #import <UIKit/UIKit.h> @