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],那么第v轮就必须出(x[v]+1)%3,或者第u轮出(x[u]+1)%3,那么第v轮就必须出x[v]。换成布尔语句描述就是xu,xv必须不同。这就需要2个子句来描述:xu为真或xv为真,xu为假或xv为假。(注意:这2个子句构成“且”的关系)。第一个子句表示xu,xv至少一个为真,第二个子句表示xu,xv至少一个为假,这样就把同时为真和同时为假的情况排除掉了。当x[u]!=x[v]时,此时我们的限制是不能出相同的,那该怎么用子句来表达呢?因为不等,所以令tmp=6-x[u]-x[v]就表示出了第3个数,且他们构成了1,2,3这1个完整的数集。我们令u1=(x[v]<=tmp),v1=(x[u]<=tmp)。此时,u1就表示不是x[u]的那个值,v1就表示不是x[v]的那个值,显然,u==u1和v==v1就是第u轮和第v轮能够出现的公共部分。这样,逻辑表达式就是“u等于!u1或v等于!v1”,就表达了u1和v1不能同时出现的含义。至此,我们分析完了w==1的情况,对于w==0,和上述情况非常相似。

3.代码:

#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define me(s)  memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;

const int N=10005;

int n,m,x[N],sn,S[N*2];
vector<int>g[N*2];

bool mark[N*2];

void init()
{
    rep(i,2*n)g[i].clear();
    me(mark);
}

void add(int u,int x,int v,int y)
{
    u=u*2+x;
    v=v*2+y;
    g[u^1].push_back(v);
    g[v^1].push_back(u);
}

bool dfs(int u)
{
    if(mark[u^1])return false;
    if(mark[u])return true;
    mark[u]=true;
    S[sn++]=u;
    rep(i,g[u].size())
    {
        int v=g[u][i];
        if(!dfs(v))return false;
    }
    return true;
}

bool solve()
{
    for(int i=0;i<2*n;i+=2)
    if(!mark[i]&&!mark[i+1])
    {
        sn=0;
        if(!dfs(i))
        {
            rep(j,sn)mark[S[j]]=false;
            sn=0;
            if(!dfs(i+1))return false;
        }
    }
    return true;
}

int main()
{
    int T;
    scanf("%d",&T);
    for(int kase=1;kase<=T;kase++)
    {
        init();
        scanf("%d%d",&n,&m);
        int tmp;
        rep(i,n)
        scanf("%d",&x[i]);
        int u,v,w;
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            u--,v--;
            int tmp=6-x[u]-x[v];
            int u1=x[v]<=tmp;
            int v1=x[u]<=tmp;
            if(w==1)
            {
                if(x[u]==x[v])
                {
                    add(u,1,v,1);
                    add(u,0,v,0);
                }
                else add(u,!u1,v,!v1);
            }
            else
            {
                if(x[u]==x[v])
                {
                    add(u,0,v,1);
                    add(u,1,u,0);
                }
                else
                {
                    add(u,u1,u,u1);
                    add(v,v1,v,v1);
                }
            }
        }
        printf("Case #%d: %s\n",kase,solve()?"yes":"no");
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 09:28:58

HDU 4115 Eliminate the Conflict (2011年成都赛区现场赛E题)的相关文章

HDU 4119 Isabella&#39;s Message (2011年成都赛区现场赛I题)

1.题目描述:点击打开链接 2.解题思路:本题是一道模拟题,要求模拟一个解密的过程,练习这么久第一次做模拟题1Y了,内心还是很激动的~.只需要根据题意,记录* 所在的位置即可,然后每次都是先解密,后顺时针旋转90度.把每次解密的信息放到一个vector里,接下来就是连接它们,得到解密后的字符串,在map中查找这些单词是否存在即可.如果都存在,就把这条解密信息放到ans中,最后对ans排序,输出ans[0]就是答案. 3.代码: //#pragma comment(linker, "/STACK:

HDU 4422 The Little Girl who Picks Mushrooms (2012年成都赛区现场赛C题)

1.题目描述:点击打开链接 2.解题思路:本题是一道简单模拟题,然而,自己的方法不对WA了很多次==.最后不得不弃用自己的思路了.首先用-1表示还没有使用过的位置.可以每次枚举3个位置,如果发现这3个位置中没有-1且他们的和不能被1024整除,那么return 0,否则,找到没有被标记的另外2个位置,如果这2个位置其中一个为-1,那么直接返回1024,因为我们已经交了三个袋子了,剩下的袋子中如果又没有确定的,那么一定可以凑成1024.否则,计算这2个位置的和,然后看减去若干次1024后剩下多少,

hdu 4431 第37届ACM/ICPC 天津赛区现场赛A题 枚举

题意:就是给了13张牌.问增加哪些牌可以胡牌.m是数字,s是条,p是筒,c是数字 胡牌有以下几种情况: 1.一个对子 +  4组 3个相同的牌或者顺子.  只有m.s.p是可以构成顺子的.东西南北这样的牌没有顺子. 2.7个不同的对子. 3.1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.  这13种牌每种都有,而且仅有这13种牌.肯定是有一种2张.其他的1张. 模拟即可,第一个对子的情况需要枚举 很麻烦的模拟,但是貌似稳银的很需要这题,所以这种难度必须要弄懂,加油

hdu 4438 第37届ACM/ICPC 天津赛区现场赛H题

题意:Alice和Bob两个人去打猎,有两种(只)猎物老虎和狼: 杀死老虎得分x,狼得分y: 如果两个人都选择同样的猎物,则Alice得分的概率是p,则Bob得分的概率是(1-p): 但是Alice事先知道Bob先选老虎的概率是Q,问Alice得分的期望最大值是 求期望 如果先去打老虎,则会有bob先去打狼和bob去打老虎两种情况,期望相加则是alice去打老虎的期望,然后求打狼的期望,比较大小即可 1 #include<cstdio> 2 #include<iostream> 3

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(2-sat 判解存在性)

题意: 有两个人玩一个石头剪刀布的游戏,两个人连续玩N轮,给出其中一个人的N轮出的情况和该人对另外一个人的一些限制条件,有两种限制:每种限制表示为:(a,b,c) ,如果c==0 则表示该人对另外一个人的限制为第a局和第b局出的应该一样,如果c==1表示不一样,问另外一个人是否有赢(规定每轮都不输就称赢)的可能. 思路:所以可以推出每轮必须出能平或赢的动作(两种选择)所以是2-sat.再找到约束关系即可 #include<cstdio> #include<iostream> #in

hdu 4031 2011成都赛区网络赛A题 线段树 ***

就是不知道时间该怎么处理,想了好久,看了别人的题解发现原来是暴力,暴力也很巧妙啊,想不出来的那种  -_-! 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9