传送门

 

题解:

  根据矛盾关系构造布尔公式。

  令 0~n-1 表示妻子, n~2*n-1 表示丈夫

  A1 C1

  A2 C2

  如果C1为0,C2为0,对应的布尔公式为 (A1+n)V(A2+n)

  如果C1为0,C2为1,对应的布尔公式为 (A1+n)V(A2)

  如果C1为1,C2为0,对应的布尔公式为 (A1)V(A2+n)

  如果C1为1,C2为1,对应的布尔公式为 (A1)V(A2)

  判断是否存在一组解,使得所有满足条件的合取范式 ((A1+n)V(A2+n))∧((A1+n)V(A2))∧((A1)V(A2+n))∧((A1)V(A2)) 的值为真;

  如果存在,输出YES,反之,输出NO.

  讲析取式转化成两个蕴含式,以此构图,然后进行强连通分量分解,求出所属强连通分量的拓扑序。

  如果有 scc[i] == scc[n+i] 则无解,输出NO,反之,一定有解,输出YES。

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 using namespace std;
 6 #define pb push_back
 7 #define mem(a,b) (memset(a,b,sizeof a))
 8 const int maxn=1e3+50;
 9 
10 int n,m;
11 int scc[2*maxn];
12 bool vis[2*maxn];
13 vector<int >vs;
14 vector<int >G[2*maxn],rG[2*maxn];
15 void addEdge(int u,int v)
16 {
17     G[u].pb(v);
18     rG[v].pb(u);
19 }
20 void Dfs(int u)
21 {
22     vis[u]=true;
23     for(int i=0;i < G[u].size();++i)
24     {
25         int to=G[u][i];
26         if(!vis[to])
27             Dfs(to);
28     }
29     vs.pb(u);
30 }
31 void rDfs(int u,int k)
32 {
33     scc[u]=k;
34     vis[u]=true;
35     for(int i=0;i < rG[u].size();++i)
36     {
37         int to=rG[u][i];
38         if(!vis[to])
39             rDfs(to,k);
40     }
41 }
42 void SCC()
43 {
44     mem(vis,false);
45     vs.clear();
46     for(int i=0;i < 2*n;++i)
47         if(!vis[i])
48             Dfs(i);
49     int k=0;
50     mem(vis,false);
51     for(int i=vs.size()-1;i >= 0;--i)
52     {
53         int u=vs[i];
54         if(!vis[u])
55             rDfs(u,++k);
56     }
57 }
58 void Init()
59 {
60     for(int i=0;i < 2*maxn;++i)
61         G[i].clear(),rG[i].clear();
62 }
63 int main()
64 {
65     while(~scanf("%d%d",&n,&m))
66     {
67         Init();
68         for(int i=1;i <= m;++i)
69         {
70             int a1,c1;
71             int a2,c2;
72             scanf("%d%d%d%d",&a1,&a2,&c1,&c2);
73             int x=a1+(c1 == 0 ? 1:0)*n;//矛盾关系对应的布尔公式为(xVy),转化成两个蕴含式即为有向图中对应的边
74             int y=a2+(c2 == 0 ? 1:0)*n;
75             addEdge((x >= n ? x-n:x+n),y);
76             addEdge((y >= n ? y-n:y+n),x);
77         }
78         SCC();
79         bool flag=false;
80         for(int i=0;i < n;++i)
81             if(scc[i] == scc[i+n])
82                 flag=true;
83         if(flag)
84             printf("NO\n");
85         else
86             printf("YES\n");
87     }
88 }
View Code

相关文章:

  • 2021-08-22
  • 2021-10-16
  • 2021-08-15
  • 2021-09-25
  • 2021-11-06
  • 2022-12-23
  • 2021-06-30
  • 2022-12-23
猜你喜欢
  • 2021-07-13
  • 2022-12-23
  • 2022-12-23
  • 2021-12-19
  • 2022-12-23
  • 2021-06-29
  • 2021-10-19
相关资源
相似解决方案