• hdu 4115(2-SAT) 2011 成都现场赛E题


    题意:两个人玩剪刀石头布,你知道对手出拳的序列(就是每一步出哪个)给你两种限制,i与j相同和不相同。你赢的条件是你不能输给对方一次,问你能不能赢。

    思路:典型的2-SAT题目,对于每次猜拳,排除你会输的那一次然后就只剩两个选择了,接下来就是分类讨论。

    我们定义第一个能出的为真,另一个为假

    首先分成 i次 与j次不能出的相同,那么 

      a b 1 表示 a^b = 1

      a b 0 表示 a^b = 0

    然后是不同的,那么

      对于a b 1情况

        a b 出那个已经知道了

      a b 0情况

        !a->b ^ !b->a  都能出的为假

        a->!b ^ b->!a  都能出的为真

    代码如下:

      1 /**************************************************
      2  * Author     : xiaohao Z
      3  * Blog     : http://www.cnblogs.com/shu-xiaohao/
      4  * Last modified : 2014-03-22 16:59
      5  * Filename     : hdu_chengdu2.cpp
      6  * Description     : 
      7  * ************************************************/
      8 
      9 #include <iostream>
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <cstdlib>
     13 #include <cmath>
     14 #include <algorithm>
     15 #include <queue>
     16 #include <stack>
     17 #include <vector>
     18 #include <set>
     19 #include <map>
     20 #define MP(a, b) make_pair(a, b)
     21 #define PB(a) push_back(a)
     22 
     23 using namespace std;
     24 typedef long long ll;
     25 typedef pair<int, int> pii;
     26 typedef pair<unsigned int,unsigned int> puu;
     27 typedef pair<int, double> pid;
     28 typedef pair<ll, int> pli;
     29 typedef pair<int, ll> pil;
     30 
     31 const int INF = 0x3f3f3f3f;
     32 const double eps = 1E-6;
     33 const int LEN = 100000+10;
     34 int n, m, chu[LEN][4], vis[LEN], sccn[LEN];
     35 vector<int> Map[LEN], rMap[LEN], vs;
     36 
     37 void dfs(int v){
     38     vis[v] = 1;
     39     for(int i=0; i<Map[v].size(); i++) if(!vis[Map[v][i]]) dfs(Map[v][i]);
     40     vs.PB(v);
     41 }
     42 
     43 void rdfs(int v, int k){
     44     vis[v] = 1;
     45     sccn[v] = k;
     46     for(int i=0; i<rMap[v].size(); i++) if(!vis[rMap[v][i]]) rdfs(rMap[v][i], k);
     47 }
     48 
     49 int scc(){
     50     memset(vis, 0, sizeof vis);
     51     vs.clear();
     52     for(int v=0; v<2*n; v++) if(!vis[v]) dfs(v);
     53     memset(vis, 0, sizeof vis);
     54     int k = 0;
     55     for(int i=vs.size()-1; i>=0; i--) if(!vis[vs[i]]) rdfs(vs[i], k++);
     56     return k;
     57 }
     58 
     59 bool twosat(){
     60     scc();
     61 //    for(int i=0; i<2*n; i++)cout << sccn[i] << ' ';
     62 //    cout << endl;
     63     for(int i=0; i<2*n; i+=2){
     64         if(sccn[i] == sccn[i^1]){
     65             //cout << i << endl;
     66             return false; 
     67         }    
     68     }
     69     return true;
     70 }
     71 
     72 void add(int a, int b){
     73     Map[a].PB(b);
     74     rMap[b].PB(a);
     75 }
     76 
     77 void addNot(int a, int b){
     78     a*=2; b*=2;
     79     add(a, b^1);
     80     add(b^1, a);
     81     add(b, a^1);
     82     add(a^1, b);
     83 }
     84 
     85 void addYes(int a, int b){
     86     a*=2; b*=2;
     87     add(a, b);
     88     add(b, a);
     89     add(a^1, b^1);
     90     add(b^1, a^1);
     91 }
     92 
     93 void addSame(int a){
     94     add(a^1, a);
     95 }
     96 
     97 void addNotSame(int a, int b){
     98     add(a, b^1);
     99     add(b, a^1);
    100 }
    101 
    102 int main()
    103 {
    104 //    freopen("in.txt", "r", stdin);
    105     
    106     int T, a, b, c;
    107     scanf("%d", &T);
    108     for(int kase=1; kase<=T; kase++){
    109         for(int i=0; i<LEN; i++) Map[i].clear();
    110         for(int i=0; i<LEN; i++) rMap[i].clear();
    111         memset(chu, 0, sizeof chu);
    112         scanf("%d%d", &n, &m);
    113         for(int i=0; i<n; i++){
    114             int tmp;
    115             scanf("%d", &tmp);
    116             chu[i][0] = tmp;
    117             chu[i][(tmp)%3+1] = 1;
    118         }
    119         for(int i=0; i<m; i++){
    120             scanf("%d%d%d", &a, &b, &c);
    121             a--; b--;
    122             if(chu[a][0] == chu[b][0]){
    123                 if(c == 1) addNot(a, b);
    124                 else addYes(a, b);
    125             }else{
    126                 int fa = -1, fb = -1;
    127                 for(int j=1; j<4; j++){
    128                     if(!chu[a][j]) fa++;
    129                     if(!chu[b][j]) fb++;
    130                     if(chu[a][j] == chu[b][j] && chu[b][j] == 0) break;
    131                 }
    132                 if(c == 0){
    133                     addSame((2*a)^fa);
    134                     addSame((2*b)^fb);
    135                 }else{
    136                     addNotSame((2*a)^fa, (2*b)^fb);
    137                 }
    138             }
    139         }
    140         printf("Case #%d: ", kase);
    141         if(twosat())printf("yes
    ");
    142         else printf("no
    ");
    143     }
    144     return 0;
    145 }
    View Code
    奔跑吧!少年!趁着你还年轻
  • 相关阅读:
    前端面试题—Js
    前端面试题—css
    前端面试题—html
    JavaScript 闭包
    JavaScript 计算斐波那切数列
    JavaScript continue使用
    JavaScript break 使用
    JavaScript 综合运算 (数字运算符+比较运算符+逻辑运算符)
    JavaScript 逻辑运算符 特殊字符 纯数字字符串
    JavaScript 比较运算符 特殊字符 纯数字字符串
  • 原文地址:https://www.cnblogs.com/shu-xiaohao/p/3618269.html
Copyright © 2020-2023  润新知