zoukankan      html  css  js  c++  java
  • hdu 3062 基础的2sat

    题意:

    Party

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4035 Accepted Submission(s): 1300


    Problem Description
    有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?

    Input
    n: 表示有n对夫妻被邀请 (n<= 1000)
    m: 表示有m 对矛盾关系 ( m < (n - 1) * (n -1))

    在接下来的m行中,每行会有4个数字,分别是 A1,A2,C1,C2
    A1,A2分别表示是夫妻的编号
    C1,C2 表示是妻子还是丈夫 ,0表示妻子 ,1是丈夫
    夫妻编号从 0 到 n -1

    Output
    如果存在一种情况 则输出YES
    否则输出 NO

    Sample Input
    2 1 0 1 1 1

    Sample Output
    YES

    思路:
         基础的2sat,不会的建议看根据对称性解析2sat的那个, 把夫妻看成基础对,排斥的两个人看成排斥对,直接建边就行了,缩点我用的是双深搜的强连通。

    #include<stdio.h>
    #include<string.h>
    #include<stack>
    
    #define N_node 2000 + 10
    #define N_edge 2000000 + 100
    
    using namespace std;
    
    typedef struct
    {
       int to ,next;
    }STAR;
    
    STAR E1[N_edge] ,E2[N_edge];
    int list1[N_node] ,list2[N_node] ,tot;
    int mark[N_node] ,Belong[N_node] ,cnt;
    stack<int>st;
    
    void add(int a ,int b)
    {
       E1[++tot].to = b;
       E1[tot].next = list1[a];
       list1[a] = tot;
       
       E2[tot].to = a;
       E2[tot].next = list2[b];
       list2[b] = tot;
    }
    
    void DFS1(int s)
    {
       mark[s] = 1;
       for(int k = list1[s] ;k ;k = E1[k].next)
       {
          int xin = E1[k].to;
          if(!mark[xin])
          {
             mark[xin] = 1;
             DFS1(xin);
          }
       }
       st.push(s);
    }
    
    void DFS2(int s)
    {
       mark[s] = 1;
       Belong[s] = cnt;
       for(int k = list2[s] ;k ;k = E2[k].next)
       {
          int xin = E2[k].to;
          if(!mark[xin])
          {
             mark[xin] = 1;
             DFS2(xin);
          }
       }
    }
    
    int main ()
    {
       int n ,m ,i ,a ,b ,c ,d;
       while(~scanf("%d %d" ,&n ,&m))
       {
          memset(list1 ,0 ,sizeof(list1));
          memset(list2 ,0 ,sizeof(list2));
          tot = 1;
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d %d %d" ,&a ,&b ,&c ,&d);
             a = a * 2 + c,b = b * 2 + d;
             add(a ,b^1) ,add(b ,a^1);
          }
          while(!st.empty()) st.pop();
          memset(mark ,0 ,sizeof(mark));
          for(i = 1 ;i <= n * 2 - 1 ;i ++)
          if(!mark[i])DFS1(i);
          memset(mark ,0 ,sizeof(mark));
          cnt = 0;
          while(!st.empty())
          {
             int xin = st.top();
             st.pop();
             if(!mark[xin])
             {
                ++cnt;
                DFS2(xin);
             }
          } 
          int mk = 0;
          for(i = 0 ;i < n ;i += 2)
          {
             if(Belong[i] == Belong[i^1])
             mk = 1;
          }
          if(mk)puts("NO");
          else puts("YES");
       }
       return 0;
    }    
    


  • 相关阅读:
    unity 反编译 step2 dll -->reflector
    unity 反编译 step1 disUnity
    rpg
    cmake使用
    linux mysqld的启动过程
    unity内存加载和释放
    Linux下MySql数据库常用操作
    MySQL主从复制与读写分离(非原创,谢绝膜拜)
    linux下IPTABLES配置详解
    linux下查看端口的占用情况
  • 原文地址:https://www.cnblogs.com/csnd/p/12063022.html
Copyright © 2011-2022 走看看