poj 3678(SCC+2-SAT)

传送门:Problem 3678

https://www.cnblogs.com/violet-acmer/p/9769406.html

难点:

  题意理解+构图

题意:

  有n个点 v[0,2......,n-1](v[i]值为0或1),边(a[i],b[i])间的权值为c[i],现在给出它们之间的一些逻辑运算的结果(比如c[1]=a[1] & b[1] = 1),逻辑运算有AND OR XOR三种,问是否存在一种满足所有条件的取值方案。

构图难点:

  如果类似 u v 1 AND这样的数据,说明u,v的1必须都选,那么就把u的0连向u的1,v的0连向v的1,这样的目的是使得推出矛盾;

  同理 u v 0 or 这样的数据,说明u,v的0必须都选,那么就把u的1连向u的0,v的1连向v的0,这样的目的是使得推出矛盾;

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 maxV=1e3+50;
  9 const int maxE=1e6+50;
 10 
 11 int n,m;
 12 int a[maxE],b[maxE],c[maxE];
 13 char op[4];
 14 int scc[2*maxV];
 15 bool vis[2*maxV];
 16 vector<int >vs;
 17 vector<int >G[2*maxV],rG[2*maxV];
 18 void addEdge(int u,int v)
 19 {
 20     G[u].pb(v);
 21     rG[v].pb(u);
 22 }
 23 void Dfs(int u)
 24 {
 25     vis[u]=true;
 26     for(int i=0;i < G[u].size();++i)
 27     {
 28         int to=G[u][i];
 29         if(!vis[to])
 30             Dfs(to);
 31     }
 32     vs.pb(u);
 33 }
 34 void rDfs(int u,int k)
 35 {
 36     vis[u]=true;
 37     scc[u]=k;
 38     for(int i=0;i < rG[u].size();++i)
 39     {
 40         int to=rG[u][i];
 41         if(!vis[to])
 42             rDfs(to,k);
 43     }
 44 }
 45 void SCC()
 46 {
 47     mem(vis,false);
 48     vs.clear();
 49     for(int i=0;i < 2*n;++i)
 50         if(!vis[i])
 51             Dfs(i);
 52     mem(vis,false);
 53     int k=0;
 54     for(int i=vs.size()-1;i >= 0;--i)
 55     {
 56         int to=vs[i];
 57         if(!vis[to])
 58             rDfs(to,++k);
 59     }
 60 }
 61 void Init()
 62 {
 63     for(int i=0;i < maxV;++i)
 64         G[i].clear(),rG[i].clear();
 65 }
 66 int main()
 67 {
 68     scanf("%d%d",&n,&m);
 69     Init();
 70     for(int i=1;i <= m;++i)
 71     {
 72         scanf("%d%d%d%s",a+i,b+i,c+i,op);
 73         switch (op[0])
 74         {
 75         case 'A':
 76             if(c[i] == 0)
 77                 addEdge(a[i],b[i]+n),addEdge(b[i],a[i]+n);
 78             else
 79                 addEdge(a[i]+n,a[i]),addEdge(b[i]+n,b[i]);
 80             break;
 81         case 'O':
 82             if(c[i] == 1)
 83                 addEdge(a[i]+n,b[i]),addEdge(b[i]+n,a[i]);
 84             else
 85                 addEdge(a[i],a[i]+n),addEdge(b[i],b[i]+n);
 86             break;
 87         case 'X':
 88             if(c[i] == 1)
 89             {
 90                 addEdge(a[i],b[i]+n),addEdge(b[i]+n,a[i]);
 91                 addEdge(a[i]+n,b[i]),addEdge(b[i],a[i]+n);
 92             }
 93             else
 94             {
 95                 addEdge(a[i],b[i]),addEdge(b[i],a[i]);
 96                 addEdge(a[i]+n,b[i]+n),addEdge(b[i]+n,a[i]+n);
 97             }
 98             break;
 99         }
100     }
101     SCC();
102     bool flag=false;
103     for(int i=0;i < n;++i)
104         if(scc[i] == scc[i+n])
105             flag=true;
106     if(flag)
107         printf("NO
");
108     else
109         printf("YES
");
110 
111 }
View Code
原文地址:https://www.cnblogs.com/violet-acmer/p/9775216.html