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;
}    


原文地址:https://www.cnblogs.com/csnd/p/12063022.html