HDU 4115 Eliminate the Conflict(2-sat 判解存在性)

题意:

有两个人玩一个石头剪刀布的游戏,两个人连续玩N轮,给出其中一个人的N轮出的情况和该人对另外一个人的一些限制条件,有两种限制:每种限制表示为:(a,b,c) ,如果c==0 则表示该人对另外一个人的限制为第a局和第b局出的应该一样,如果c==1表示不一样,问另外一个人是否有赢(规定每轮都不输就称赢)的可能。

思路:所以可以推出每轮必须出能平或赢的动作(两种选择)所以是2-sat。再找到约束关系即可

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 20010;

struct Edge
{
    int v,next;
}es[N*100];
int val[N];
int head[N];
int n,m,cnt;

inline void add_edge(int u,int v)
{
    es[cnt].v=v;
    es[cnt].next=head[u];
    head[u]=cnt++;
}

int tmp[N],sta[N],dfn[N],low[N],index,top;

void tarjan(int u)
{
    tmp[u]=1;
    sta[++top]=u;
    dfn[u]=low[u]=++index;
    for(int i=head[u];~i;i=es[i].next)
    {
        int v=es[i].v;
        if(tmp[v]==0) tarjan(v);
        if(tmp[v]==1) low[u]=min(low[u],low[v]);
    }
    if(dfn[u]==low[u])
    {
        do
        {
            int v=sta[top];
            low[v]=low[u];
            tmp[v]=2;
        }while(sta[top--]!=u);
    }
}
bool judge()
{
    for(int i=0;i<2*n;i++)
    {
        if(low[i]==low[i^1]) return false;
    }
    return true;
}

void ini()
{
    memset(head,-1,sizeof(head));
    memset(tmp,0,sizeof(tmp));
    index=top=cnt=0;
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++)
    {
        ini();
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            int c,u=i<<1;
            scanf("%d",&c);
            val[u]=c;
            val[u^1]=c%3+1;
        }
        for(int i=1;i<=m;i++)
        {
            int u,v,op;
            scanf("%d%d%d",&u,&v,&op);
            u=(u-1)<<1,v=(v-1)<<1;
            if(op==0)
            {
                if(val[u]==val[v]) add_edge(u,v);
                else if(val[u]==val[v^1]) add_edge(u,v^1);
                else add_edge(u,u^1);
                if(val[u^1]==val[v]) add_edge(u^1,v);
                else if(val[u^1]==val[v^1]) add_edge(u^1,v^1);
                else add_edge(u^1,u);
                if(val[v]==val[u]) add_edge(v,u);
                else if(val[v]==val[u^1]) add_edge(v,u^1);
                else add_edge(v,v^1);
                if(val[v^1]==val[u]) add_edge(v^1,u);
                else if(val[v^1]==val[u^1]) add_edge(v^1,u^1);
                else add_edge(v^1,v);
            }
            else
            {
                if(val[u]==val[v]) add_edge(u,v^1),add_edge(v,u^1);
                else if(val[u]==val[v^1]) add_edge(u,v),add_edge(v^1,u^1);
                if(val[u^1]==val[v]) add_edge(u^1,v^1),add_edge(v,u);
                else if(val[u^1]==val[v^1]) add_edge(u^1,v),add_edge(v^1,u);
            }
        }
        for(int i=0;i<2*n;i++) if(tmp[i]==0) tarjan(i);
        if(judge())
            printf("Case #%d: yes\n",cas);
        else printf("Case #%d: no\n",cas);
    }
    return 0;
}
时间: 2024-11-05 19:37:09

HDU 4115 Eliminate the Conflict(2-sat 判解存在性)的相关文章

hdu 4115 Eliminate the Conflict

Description Conflicts are everywhere in the world, from the young to the elderly, from families to countries. Conflicts cause quarrels, fights or even wars. How wonderful the world will be if all conflicts can be eliminated.Edward contributes his lif

HDU 4115 Eliminate the Conflict(2-sat)

HDU 4115 Eliminate the Conflict 题目链接 题意:Alice和Bob这对狗男女在玩剪刀石头布,已知Bob每轮要出什么,然后Bob给Alice一些限制,1表示i轮和j轮Alice必须出不一样的,0表示必须出一样的,如果Alice有一局输了就算输了,否则就是赢,问Alice是否能赢 思路:2-sat问题,已经Bob出什么,Alice要么就出赢的要么就出平的,然后加上m个约束就是2-sat问题了 代码: #include <cstdio> #include <cs

HDU 4115 Eliminate the Conflict【2-sat】

转载请注明出处:http://blog.csdn.net/u013912596 题目大意: Alice和Bob玩若干轮石头剪刀布的游戏,Alice已经知道了Bob在每一轮会出什么,但是Bob会给出一些Alice的限制条件,问Alice在不打破这些限制的情况下,有没有可能赢. 限制格式为(i,j,w),i,j代表第几轮,w=1的话,要求Alice在第i轮和第j轮的策略不能相同,w=0的话,要求Alice在第i轮和第j轮的策略必须相同. 思路: 刚开始以为这个题是个DP,按照这个想了一下,发现要求相

HDU 4115 Eliminate the Conflict (2011年成都赛区现场赛E题)

1.题目描述:点击打开链接 2.解题思路:本题属于2-SAT问题,第一次做这种题,还是很感兴趣的.2-SAT解决的是给定m条语句,每一条语句形如"xi为真或xj为假",问你是否可能让所有的语句都成立.那么不难发现,本题就属于一种2-SAT问题. 首先,根据题意可知,第i轮有2种出法,要么是x[i],要么是(x[i]+1)%3.我们令xi为真表示出x[i],xi为假表示出(x[i]+1)%3.对于w==1的情况,我们要分2种情况讨论:当x[u]==x[v]时,表示第u轮出x[u],那么第

POJ 3207 Ikki&#39;s Story IV - Panda&#39;s Trick(2-sat判解存在性)

题意:平面上,一个圆,圆的边上按顺时针放着n个点.现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接.给你的信息中,每个点最多只会连接的一条边.问能不能连接这m条边,使这些边都不相交. 算比较裸的题目了,关键找到如何判断两对点交不交叉的关系就好 #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector&g

Eliminate the Conflict HDU - 4115

Conflicts are everywhere in the world, from the young to the elderly, from families to countries. Conflicts cause quarrels, fights or even wars. How wonderful the world will be if all conflicts can be eliminated. Edward contributes his lifetime to in

hdu 3715 hdu 1816 hdu 4115 (2-sat)

三个2-sat问题,我总结一下自己的经验,我还是太菜,好久没做2-sat,又不太会建图了 总结:2-sat问题的核心就是建模 建模的思想很重要: 1.首先要怎么才能看出来是2-sat问题,对于每一个点,都有两种选择,则可以考虑是2-sat 比如让你在n组里面选n个,每组2个东西,这样就是2-sat的模型 2.确定是2-sat问题之后,就是要确定,拥有两种选择的对象,比如下面的例题里,有的是x[i]的取值有0或者1两种,有的是一串钥匙有两个,但你只能选择其中一个,则对于一个钥匙,它的取值有取或者不

hdu 4115 2-SAT

1 /* 2 题解:2-SAT 3 一开始每一个round都有两种状态可选,并且选了每种状态有后面的限制其中一种选后另一状态的状态也被固定, 4 十分符合2-SAT的用法: 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <iostream> 9 #include <vector> 10 #include <queue> 11 12 #define clr(a,b) (memset

HDU 5154 Harry and Magical Computer 有向图判环

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5154 题解: 有向图判环. 1.用dfs,正在访问的节点标记为-1,已经访问过的节点标记为1,没有访问过的节点标记为0,如果访问到-1的节点说明说有环. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 t