POJ 3678 Katu Puzzle (2-SAT,常规)

 

 

题意:给出n个点,每个点上有一个数字可以0或1,然后给出m条限制,要求a和b两个点上的数字满足 a op b = c,op和c都是给定。问是否能够有一组解满足所有限制?(即点上的数字是0是1由你决定)

思路:题意很清晰了,难点在建图。要考虑所有可能的冲突:

当op为and:  (1)c为0时,其中1个必为0。

        (2)c为1时,两者必为1。要加两条边,形如 a0->a1。

当op为or:   (1)c为0时,两者必为0。要加两条边,形如 a1->a0。

        (2)c为1时,其中1个必为1。

当op为xor:  (1)c为0时,两者必定相同。

        (2)c为1时,两者必定不同。

都是按照冲突来建图就行,有没有解留给DFS去判定。

 

 

  1 #include <iostream>

  2 #include <stdio.h>

  3 #include <string.h>

  4 #include <vector>

  5 #include <stack>

  6 #include <algorithm>

  7 #include <map>

  8 //#include <bits/stdc++.h>

  9 #define LL long long

 10 #define pii pair<int,int>

 11 #define INF 0x7f7f7f7f

 12 using namespace std;

 13 const int N=1000*2+5;

 14 int res[N][N];

 15 vector<int> vect[N*2];

 16 map<string,int> mapp;

 17 

 18 void init()

 19 {

 20     string tmp="AND";

 21     mapp[tmp]=1;

 22     tmp="OR";

 23     mapp[tmp]=2;

 24     tmp="XOR";

 25     mapp[tmp]=3;

 26 }

 27 int s[N*2], col[N*2], c;

 28 bool color(int x)

 29 {

 30     if(col[x^1])    return false;

 31     if(col[x])      return true;

 32     col[x]=2;

 33     s[c++]=x;

 34     for(int i=0; i<vect[x].size(); i++)

 35         if(!color(vect[x][i]))  return false;

 36     return true;

 37 }

 38 

 39 

 40 int cal(int n)

 41 {

 42     memset(col,0,sizeof(col));

 43     memset(s,0,sizeof(s));

 44     for(int i=0; i<n; i+=2)

 45     {

 46         if(!col[i]&&!col[i+1])

 47         {

 48             c=0;

 49             if(!color(i))

 50             {

 51                 while(c)    col[s[--c]]=0;

 52                 if(!color(i+1)) return false;

 53             }

 54         }

 55     }

 56     return true;

 57 }

 58 

 59 int main()

 60 {

 61     freopen("input.txt", "r", stdin);

 62     init();

 63     string op;

 64     int n, m, a, b, c;

 65     while(~scanf("%d%d",&n,&m))

 66     {

 67         memset(res,0xf0,sizeof(res));

 68         for(int i=n*2; i>=0; i--)   vect[i].clear();

 69 

 70         for(int i=0; i<m; i++)

 71         {

 72             scanf("%d%d%d",&a,&b,&c);

 73             cin>>op;

 74             res[a][b]=c;

 75             int t=mapp[op];

 76             //设i*2为0,i*2+1为1

 77             if(t==1)    //and

 78             {

 79                 if(c==0)    //其中必有1个为0

 80                 {

 81                     vect[a*2+1].push_back(b*2);

 82                     vect[b*2+1].push_back(a*2);

 83 

 84                 }

 85                 else        //两者必为1

 86                 {

 87                     vect[a*2].push_back(a*2+1); //指向自己

 88                     vect[b*2].push_back(b*2+1);

 89                 }

 90             }

 91             else if(t==2)   //or

 92             {

 93                 if(c==0)    //两者必为0

 94                 {

 95                     vect[a*2+1].push_back(a*2);

 96                     vect[b*2+1].push_back(b*2);

 97                 }

 98                 else        //其中必有1个为1

 99                 {

100                     vect[a*2].push_back(b*2+1);

101                     vect[b*2].push_back(a*2+1);

102                 }

103             }

104             else        //XOR

105             {

106                 if(c==0)    //两者必定相同

107                 {

108                     vect[a*2].push_back(b*2);

109                     vect[b*2].push_back(a*2);

110                     vect[a*2+1].push_back(b*2+1);

111                     vect[b*2+1].push_back(a*2+1);

112                 }

113                 else        //两者必定不同

114                 {

115                     vect[a*2].push_back(b*2+1);

116                     vect[a*2+1].push_back(b*2);

117                     vect[b*2].push_back(a*2+1);

118                     vect[b*2+1].push_back(a*2);

119                 }

120             }

121         }

122         if(!cal(n<<1))    puts("NO");

123         else    puts("YES");

124     }

125     return 0;

126 }
AC代码

 

你可能感兴趣的:(poj)