2-SAT专题练习 (题解+AC代码)

寒假回老家那几天,看了蓝书的2-SAT专题介绍,觉得比较有趣。但天天串亲戚,没空刷题。开学后自己建了一个2-SAT专题训练,把经典问题都做了。觉得2-SAT难度不大,代码简单易懂。有些题构图比较有趣吧~~

2-SAT可行性的判断参照蓝书,简单易懂,自己写一遍就记住怎么写了~

我不建议学网上一些大牛的模板,太复杂了!!!比如kuangbin的2-SAT模板,写起来还是挺复杂的,我反正不会去看的。。


题目解析和代码实现我都放到GitHub上了 :2-SAT专题题解+AC代码

放一个截屏,看看成果吧~


为了方便大家想做题自己clone专题,我改成了public。 专题链接:点击打开链接


----------------------------------------------------------------------------------------------------------------------------

A:

难度不大,至于为啥错那么多。。是因为输出的字符串少打了一个字符。。。

这篇博客里有图帮助说明情况   点击打开链接


D:

题意:地图有N个城市,每个都要贴标签。
标签为正方形,而且标签的上边或下边的中点是城市,要求所有标签大小相等且不重叠。
求标签的最大边长。


分析: 求最大值二分答案。
每个城市只有在上边或下边两个状态,所以考虑构建2-SAT模型
如果两个城市横坐标之差的绝对值大于等于r,跳过
如果两个城市的纵坐标之差大于等于2r,跳过

如果两个城市纵坐标相等,只有一个贴上边,一个贴下边的情况
如果两个城市纵坐标之差绝对值小于r,则若上边的城市贴下面的标签就有矛盾,或者下边的城市贴上面的标签就会出现矛盾

如果两个城市纵坐标之差大于等于r,小于2r,则若上边城市贴下面的标签,下边城市贴上面的标签就会出现矛盾


不知道为什么,这题卡了N久。。POJ交了30多次才AC。。可也没找到啥错误。。。也不知道最后改了啥才AC的。。。


F:

题意:三种逻辑运算,and,or,xor
给出N个变量,取值0或1
M个运算式子,问是否有解

分析:建图非常经典,加深了对2-SAT模型构建的理解
2-SAT模型中,每个有向边x->y表示 选了x必选y

AND运算:
若 c == 1, x->x' y->y' 所以是自我矛盾,不会出现x,y为0的情况
若 c == 0, x'->y y'->x 表示至少有一个为0

OR运算:跟AND十分类似,略

XOR运算:
若 c == 1, x->y' x'->y y->x' y'->x
若 c == 2, x->y  y->x  x'->y' y'->x'

然后就是跑一遍可行性判断

------------------------------------------------------------------------------------------------------------------------


其他印象没那么深刻,难度不大哈哈哈~ 

我还加了蓝书的两道例题(H,I),例题的话书上的解析很详细了,这里略

其他题目的详细解析都在GitHub上面,我就不全部贴出来了。 这里只把AC代码都贴出来~

-----------------------------------------------------------------------------------------------------------------------

POJ3207 - A题

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

const int maxm = 510;
const int maxn = 1010;
struct TwoSAT{
    int n;
    bool mark[maxn*2];
    vector<int> G[maxn*2];
    int S[maxn*2],c;

    void init(int n){
        this->n = n;
        for (int i=0; i<n*2; i++) G[i].clear();
        memset(mark,0,sizeof(mark));
    }

    inline void add(int x, int y) {G[x].push_back(y); }

    bool dfs(int x) {
       if (mark[x^1]) return 0;
       if (mark[x]) return 1;
       mark[x] = 1;
       S[c++] = x;
       for (int i=0; i<G[x].size(); i++)
         if (!dfs(G[x][i])) return 0;
       return 1;
    }

    bool solve(){
        for (int i=0; i<2*n; i+=2)  if (!mark[i] && !mark[i+1]) {
            c = 0;
            if (!dfs(i)) {
                while (c>0) mark[S[--c]] = 0;
                if (!dfs(i+1)) return 0;
            }
        }
        return 1;
    }
};
TwoSAT solver;

struct Point{
   int x,y;
}p[maxm];
int n,m;

inline bool judge(int i, int j) {
   return p[j].x>=p[i].x && p[j].x<=p[i].y && p[j].y>=p[i].y;
}

int main(){
    while (scanf("%d%d",&n,&m)==2) {
        solver.init(m);
        for (int i=0; i<m; i++) {
            scanf("%d%d",&p[i].x,&p[i].y);
            if (p[i].x>p[i].y) swap(p[i].x,p[i].y);
        }

        for (int i=0; i<m; i++) {
            for (int j=i+1; j<m; j++) {
                if (judge(i,j) || judge(j,i)) {
                      solver.add(i*2,j*2+1);
                      solver.add(i*2+1,j*2);
                      solver.add(j*2,i*2+1);
                      solver.add(j*2+1,i*2);
                }
            }
        }

        if (solver.solve()) printf("panda is telling the truth...\n");
        else printf("the evil panda is lying again\n");
    }
    return 0;
}

HDU1814 - B题

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int maxn = 8000+5;
struct TwoSAT{
    int n;
    int S[maxn*2],c;
    bool mark[maxn*2];
    vector<int> G[maxn*2];

    void init(int n) {
       this->n = n;
       for (int i=0; i<n*2; i++) G[i].clear();
       memset(mark,0,sizeof(mark));
    }

    void add(int x, int y) {
        G[x].push_back(y^1);
        G[y].push_back(x^1);
    }

    bool dfs(int x) {
        if (mark[x^1]) return 0;
        if (mark[x]) return 1;
        mark[x] = 1;
        S[c++] = x;

        for (int i=0; i<G[x].size(); i++)
            if (!dfs(G[x][i])) return 0;
       return 1;
    }

    bool solve() {
        for (int i=0; i<n*2; i+=2) {
            if (!mark[i] && !mark[i+1]) {
                c = 0;
                if (!dfs(i)) {
                    while (c>0) mark[S[--c]] = 0;
                    if (!dfs(i+1)) return 0;
                }
            }
        }
        return 1;
    }

};

TwoSAT solver;
int n,m;

int main(){
    while (scanf("%d%d",&n,&m)==2) {
        solver.init(n);

        int a,b;
        for (int i=0; i<m; i++) {
            scanf("%d%d",&a,&b);
            a--; b--;
            solver.add(a,b);
        }

        if (!solver.solve()) printf("NIE\n");
        else {
            for (int i=0; i<n; i++) if (solver.mark[i<<1]) printf("%d\n",i<<1|1);
            else printf("%d\n",(i<<1)+2);
        }
    }
    return 0;
}

HDU3622 - C题

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

const double eps = 1e-8;
int dcmp(double x){
    if (fabs(x)<eps) return 0;
    return x<0?-1:1;
}

const int maxn = 100+5;
struct Point{
   int x,y;
   Point(int x=0, int y=0):x(x),y(y){}
};
Point p1[maxn],p2[maxn];
int n;

struct TwoSAT{
    int S[maxn<<1],c;
    bool mark[maxn<<1];
    vector<int> G[maxn<<1];
    int n;

    void init(int n) {
       this->n = n;
       memset(mark,0,sizeof(mark));
       for (int i=0; i<n*2; i++) G[i].clear();
    }

    void add(int x, int xval, int y, int yval) {
       x = x*2 + xval;
       y = y*2 + yval;
       G[y^1].push_back(x);
       G[x^1].push_back(y);
    }

    bool dfs(int x) {
       if (mark[x^1]) return 0;
       if (mark[x]) return 1;
       mark[x] = 1;
       S[c++] = x;

       for (int i=0; i<G[x].size(); i++)
         if (!dfs(G[x][i])) return 0;
       return 1;
    }

    bool solve() {
        for (int i=0; i<n*2; i+=2) {
            if (!mark[i] && !mark[i+1]) {
                c = 0;
                if (!dfs(i)) {
                    while (c>0) mark[S[--c]] = 0;
                    if (!dfs(i+1)) return 0;
                }
            }
        }
        return 1;
    }
};
TwoSAT solver;

double dis1[maxn][maxn][2];
double dis2[maxn][maxn][2];

inline double Length(Point a, Point b) {
   return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
}

bool judge(double mid) {
    mid = mid*2;
    solver.init(n);
    for (int i=0; i<n; i++) {
        for (int j=i+1; j<n; j++) {
             if ( dcmp(dis1[i][j][0]-mid)<0 ) solver.add(i,0,j,0);
             if ( dcmp(dis2[i][j][0]-mid)<0 ) solver.add(i,1,j,0);
             if ( dcmp(dis1[i][j][1]-mid)<0 ) solver.add(i,0,j,1);
             if ( dcmp(dis2[i][j][1]-mid)<0 ) solver.add(i,1,j,1);
        }
    }
    return solver.solve();
}

int main(){
    while (scanf("%d",&n)==1) {
        int x,y;
        for (int i=0; i<n; i++) {
            scanf("%d%d",&x,&y); p1[i] = Point(x,y);
            scanf("%d%d",&x,&y); p2[i] = Point(x,y);
        }

        for (int i=0; i<n; i++) {
            for (int j=i+1; j<n; j++) dis1[i][j][0] = Length(p1[i],p1[j]), dis1[i][j][1] = Length(p1[i],p2[j]);
            for (int j=i+1; j<n; j++) dis2[i][j][0] = Length(p2[i],p1[j]), dis2[i][j][1] = Length(p2[i],p2[j]);
        }

        double left = 0, right = 1e5;
        double mid, ans = 0;
        while (right-left>eps) {
            mid = (left+right)*0.5;
            if (judge(mid)) {
                ans = mid;
                left = mid+eps;
            }
            else right = mid-eps;
        }

        printf("%.2f\n",ans);
    }
    return 0;
}


POJ2296 - D题

#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

const int maxn = 100+5;
struct TwoSAT{
    int S[maxn*2],c;
    bool mark[maxn*2];
    vector<int> G[maxn*2];
    int n;

    bool dfs(int x) {
       if (mark[x^1]) return 0;
       if (mark[x]) return 1;
       mark[x] = 1;
       S[c++] = x;

       for (int i=0; i<G[x].size(); i++)
          if (!dfs(G[x][i])) return 0;
       return 1;
    }

    void init(int n) {
       this->n = n;
       memset(mark,0,sizeof(mark));
       for (int i=0; i<n*2; i++) G[i].clear();
    }

    void add(int x, int xval, int y, int yval) {
        x = x*2 + xval;
        y = y*2 + yval;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }



    bool solve() {
         for (int i=0; i<n*2; i+=2) {
            if (!mark[i] && !mark[i^1]) {
               c = 0;
               if (!dfs(i)) {
                  while (c>0) mark[S[--c]] = 0;
                  if (!dfs(i+1)) return 0;
               }
            }
         }
         return 1;
    }
};
TwoSAT solver;

int n;
struct Point{
   int x,y;
}p[maxn];

bool judge(int r) {
    solver.init(n);

    int up,down;
    for (int i=0; i<n; i++) {
        for (int j=0; j<i; j++) if (abs(p[i].x-p[j].x)<r){
              if (p[i].y > p[j].y) up = i, down = j;
              else up = j, down = i;
              if (p[up].y == p[down].y) {
                  solver.add(up,0,down,0);
                  solver.add(up,1,down,1);
                  continue;
              }

              if (p[up].y - p[down].y < 2*r) {
                  if (p[up].y - p[down].y < r) {
                      solver.add(up,0,up,0);
                      solver.add(down,1,down,1);
                  }
                  else {
                      solver.add(up,0,down,1);
                  }
              }
        }
    }

    return solver.solve();
}

int main(){
    int T;
    scanf("%d",&T);
    while (T--) {
       scanf("%d",&n);
       for (int i=0; i<n; i++) scanf("%d%d",&p[i].x,&p[i].y);

       int left = 0, right = 10000;
       int mid , ans = 0;
       while (left<=right) {
          mid = (left+right)>>1;
          if (judge(mid)) left = mid+1, ans = mid;
          else right = mid-1;
       }
       printf("%d\n",ans);
    }
    return 0;
}


POJ3648 - E题

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int maxn = 100+5;
struct TwoSAT{
    int n;
    int S[maxn*2],c;
    bool mark[maxn*2];
    vector<int> G[maxn*2];

    void init(int n) {
       this->n = n;
       memset(mark,0,sizeof(mark));
       for (int i=0; i<n*2; i++) G[i].clear();
    }

    void add(int x, int xval, int y, int yval) {
       x = x*2 + xval; y = y*2 + yval;
       G[x^1].push_back(y);
       G[y^1].push_back(x);
    }

    bool dfs(int x) {
       if (mark[x^1]) return 0;
       if (mark[x]) return 1;
       mark[x] = 1;
       S[c++] = x;
       for (int i=0; i<G[x].size(); i++) if (!dfs(G[x][i])) return 0;
       return 1;
    }

    bool solve(){
       for (int i=0; i<n*2; i+=2) {
          if (!mark[i] && !mark[i+1]) {
              c = 0;
              if (!dfs(i)) {
                 while (c>0) mark[S[--c]] = 0;
                 if (!dfs(i+1)) return 0;
              }
          }
       }
       return 1;
    }

};

TwoSAT solver;
int n,m;

int a1,a2;
int v1,v2;
char c1,c2;

int main(){
    while (scanf("%d%d",&n,&m)==2) {
        solver.init(n);
        while (m--) {
            scanf("%d%c%d%c",&a1,&c1,&a2,&c2);
            if (c1 == 'h') v1 = 0; else v1 = 1;
            if (c2 == 'h') v2 = 0; else v2 = 1;
            solver.add(a1,v1,a2,v2);
        }
        solver.add(0,1,0,1);

        if (!solver.solve()) printf("bad luck\n");
        else {
            for (int i=2; i<n*2; i+=2) {
               if (solver.mark[i]) printf("%dh ",i/2);
               else printf("%dw ",i/2);
            }
            printf("\n");
        }
    }
    return 0;
}


POJ3678 - F题

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int maxn = 1000+5;
struct TwoSAT{
   int n;
   int S[maxn*2],c;
   bool mark[maxn*2];
   vector<int> G[maxn*2];

   void init(int n) {
      this-> n = n;
      memset(mark,0,sizeof(mark));
      for (int i=0; i<n*2; i++) G[i].clear();
   }

   void add(int x, int xval, int y, int yval) {
      x = x*2 + xval;
      y = y*2 + yval;
      G[x].push_back(y);
   }

   bool dfs(int x) {
      if (mark[x^1]) return 0;
      if (mark[x]) return 1;
      mark[x] = 1;
      S[c++] = x;

      for (int i=0; i<G[x].size(); i++)
        if (!dfs(G[x][i])) return 0;
      return 1;
   }

   bool solve() {
       for (int i=0; i<n*2; i+=2) {
          if (!mark[i] && !mark[i+1]) {
              c = 0;
              if (!dfs(i)) {
                 while (c>0) mark[S[--c]] = 0;
                 if (!dfs(i+1)) return 0;
              }
          }
       }
       return 1;
   }

};

TwoSAT solver;
int n,m;
int a,b,c;
char s[5];

int main(){
    while (scanf("%d%d",&n,&m)==2) {
        solver.init(n);
        while (m--) {
            scanf("%d%d%d%s",&a,&b,&c,s);
            if (s[0]=='A') {
               if (c == 1) solver.add(a,0,a,1),solver.add(b,0,b,1);
               else solver.add(a,1,b,0),solver.add(b,1,a,0);
            }
            else if (s[0]=='O') {
                  if (c == 1) solver.add(a,0,b,1),solver.add(b,0,a,1);
                  else solver.add(a,1,a,0),solver.add(b,1,b,0);
            }
            else {
                  if (c == 1) solver.add(a,1,b,0),solver.add(a,0,b,1),solver.add(b,1,a,0),solver.add(b,0,a,1);
                  else solver.add(a,0,b,0),solver.add(a,1,b,1),solver.add(b,0,a,0),solver.add(b,1,a,1);
            }
        }

        if (solver.solve()) printf("YES\n"); else printf("NO\n");
    }
    return 0;
}

HDU4115 - G题

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;

const int maxn = 10000+5;
struct TwoSAT{
    int n;
    bool mark[maxn*2];
    int S[maxn*2],c;
    vector<int> G[maxn*2];

    void init(int n) {
       this->n = n;
       memset(mark,0,sizeof(mark));
       for (int i=0; i<n*2; i++) G[i].clear();
    }

    void add(int x, int xval , int y, int yval) {
        x = x*2 + xval; y = y*2 + yval;
        G[x].push_back(y);
    }

    bool dfs(int x) {
       if (mark[x^1]) return 0;
       if (mark[x]) return 1;
       mark[x] = 1;
       S[c++] = x;

       for (int i=0; i<G[x].size(); i++)
         if (!dfs(G[x][i])) return 0;
       return 1;
    }

    bool solve(){
       for (int i=0; i<n*2; i+=2) {
          if (!mark[i] && !mark[i+1]) {
             c = 0;
             if (!dfs(i)) {
                 while (c>0) mark[S[--c]] = 0;
                 if (!dfs(i+1)) return 0;
             }
          }
       }
       return 1;
    }

};
TwoSAT solver;

int n,m;
int a[maxn],b[maxn];
int x,y,z;

int main(){
    int T;
    scanf("%d",&T);
    for (int kase = 1; kase <= T; kase++) {
        scanf("%d%d",&n,&m);
        for (int i=0; i<n; i++) {
           scanf("%d",&a[i]);
           if (a[i]==1) b[i] = 2;
           else if (a[i]==2) b[i] = 3;
           else b[i] = 1;
           if (a[i]>b[i]) swap(a[i],b[i]);
        }

        solver.init(n);
        while (m--) {
           scanf("%d%d%d",&x,&y,&z);
           x--; y--;
           if (z == 0) {
              if (a[x]!=a[y]) {
                 solver.add(x,0,y,1);
                 solver.add(y,0,x,1);
              }
              if (a[x]!=b[y]) {
                 solver.add(x,0,y,0);
                 solver.add(y,1,x,1);
              }
              if (b[x]!=b[y]) {
                 solver.add(x,1,y,0);
                 solver.add(y,1,x,0);
              }
              if (b[x]!=a[y]) {
                 solver.add(x,1,y,1);
                 solver.add(y,0,x,0);
              }
           }
           else {
              if (a[x]==a[y]) {
                 solver.add(x,0,y,1);
                 solver.add(y,0,x,1);
              }
              if (a[x]==b[y]) {
                 solver.add(x,0,y,0);
                 solver.add(y,1,x,1);
              }
              if (b[x]==b[y]) {
                 solver.add(x,1,y,0);
                 solver.add(y,1,x,0);
              }
              if (b[x]==a[y]) {
                 solver.add(x,1,y,1);
                 solver.add(y,0,x,0);
              }
           }
        }

        if (solver.solve()) printf("Case #%d: yes\n",kase);
        else printf("Case #%d: no\n",kase);
    }
    return 0;
}


UVALive3211 - H题

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
using namespace std;

const int maxn = 2000+5;
struct TwoSAT {
    int n;
    vector<int> G[maxn*2];
    bool mark[maxn*2];
    int S[maxn*2],c;

    void init(int n){
        this->n = n;
        for (int i=0; i<n*2; i++) G[i].clear();
        memset(mark,0,sizeof(mark));
    }

    void add(int x, int xval, int y, int yval) {
        x = x*2 + xval;
        y = y*2 + yval;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }

    bool dfs(int x){
       if (mark[x^1]) return 0;
       if (mark[x]) return 1;
       mark[x] = 1;
       S[c++] = x;
       for (int i=0; i<G[x].size(); i++)
          if (!dfs(G[x][i])) return 0;
       return 1;
    }

    bool solve() {
       for (int i=0; i<n*2; i+=2) {
           if (!mark[i] && !mark[i+1]) {
                c = 0;
                if (!dfs(i)) {
                    while (c>0) mark[S[--c]] = 0;
                    if (!dfs(i+1)) return 0;
                }
           }
       }
       return 1;
    }
};

TwoSAT solver;
int n;
int T[maxn][2];

inline int Max(int x, int y) {return x>y?x:y; }

bool judge(int mid) {
     solver.init(n);
     for (int i=0; i<n; i++)
        for (int a=0; a<2; a++)
           for (int j=i+1; j<n; j++)
              for (int b=0; b<2; b++)
                 if (abs(T[i][a]-T[j][b])<mid) solver.add(i,a^1,j,b^1);
    return solver.solve();
}

int main(){
    while (scanf("%d",&n)==1 && n){
        int left = 0, right = 0;
        for (int i=0; i<n; i++) {
            for (int j=0; j<2; j++) {
                scanf("%d",&T[i][j]);
                right = Max(right,T[i][j]);
            }
        }

        int mid,ans;
        while (left<=right) {
            mid = (left+right)>>1;
            if (judge(mid)) {
                ans = mid;
                left = mid+1;
            }
            else right = mid-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}


UVALive3713 - I题

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int maxn = 100000+5;
struct TwoSAT{
    int n;
    int S[maxn*2],c;
    bool mark[maxn*2];
    vector<int> G[maxn*2];

    void init(int n){
       this->n = n;
       memset(mark,0,sizeof(mark));
       for (int i=0; i<2*n; i++) G[i].clear();
    }

    void add(int x, int xval, int y, int yval) {
        x = x*2 + xval;
        y = y*2 + yval;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }

    bool dfs(int x){
       if (mark[x^1]) return 0;
       if (mark[x]) return 1;
       mark[x] = 1;
       S[c++] = x;
       for (int i=0; i<G[x].size(); i++)
         if (!dfs(G[x][i])) return 0;
       return 1;
    }

    bool solve(){
        for (int i=0; i<2*n; i+=2) {
            if (!mark[i] && !mark[i+1]) {
                c = 0;
                if (!dfs(i)) {
                    while (c>0) mark[S[--c]] = 0;
                    if (!dfs(i+1)) return 0;
                }
            }
        }
        return 1;
    }
};

TwoSAT solver;
int n,m;
int total_age;
int age[maxn];

inline bool is_young(int x) { return age[x]*n<total_age; }
int main(){
    while (scanf("%d%d",&n,&m)==2 && n+m) {
        total_age = 0;
        for (int i=0; i<n; i++) scanf("%d",&age[i]), total_age += age[i];
        solver.init(n);

        int a,b;
        for (int i=0; i<m; i++) {
            scanf("%d%d",&a,&b);
            a--; b--;
            if (a==b) continue;
            solver.add(a,1,b,1);
            if (is_young(a) == is_young(b)) solver.add(a,0,b,0);
        }

        if (!solver.solve()) printf("No solution.\n");
        else {
            for (int i=0; i<n; i++)
                if (solver.mark[i*2]) printf("C\n");
                else if (age[i]*n<total_age) printf("B\n");
                else printf("A\n");
        }
    }
    return 0;
}


ZOJ3656 - J题

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int maxn = 500+5;
struct TwoSAT{
   int n;
   bool mark[maxn*2];
   int S[maxn*2],c;
   vector<int> G[maxn*2];

   void init(int n) {
       this->n = n;
       memset(mark,0,sizeof(mark));
       for (int i=0; i<n*2; i++) G[i].clear();
   }

   void add(int x, int xval, int y, int yval) {
       x = x*2 + xval; y = y*2 + yval;
       G[x].push_back(y);
   }

   bool dfs(int x) {
      if (mark[x^1]) return 0;
      if (mark[x]) return 1;
      mark[x] = 1;
      S[c++] = x;

      for (int i=0; i<G[x].size(); i++)
        if (!dfs(G[x][i])) return 0;
      return 1;
   }

   bool solve() {
      for (int i=0; i<n*2; i+=2) {
         if (!mark[i] && !mark[i+1]) {
            c = 0;
            if (!dfs(i)) {
                while (c>0) mark[S[--c]] = 0;
                if (!dfs(i+1)) return 0;
            }
         }
      }
      return 1;
   }
};

TwoSAT solver;
int n;
int mat[maxn][maxn];

inline bool judge(){
   for (int i=0; i<n; i++) {
       if (mat[i][i]!=0) return 0;
       for (int j=i+1; j<n; j++) if (mat[i][j] != mat[j][i]) return 0;
   }
   return 1;
}

int main(){
    while (scanf("%d",&n)==1) {
       for (int i=0; i<n; i++)
         for (int j=0; j<n; j++) scanf("%d",&mat[i][j]);

       if (!judge()) {
           printf("NO\n");
           continue;
       }

       bool flag = 1;
       for (int k=0; k<31; k++) {
           solver.init(n);
           for (int i=0; i<n; i++) {
              for (int j=i+1; j<n; j++) {
                   if (i%2==1 && j%2==1) {
                       if (mat[i][j]&1) {
                            solver.add(i,0,j,1);
                            solver.add(j,0,i,1);
                       }
                       else {
                            solver.add(i,1,i,0);
                            solver.add(j,1,j,0);
                       }
                   }
                   else if (i%2==0 && j%2==0) {
                         if (mat[i][j]&1) {
                             solver.add(i,0,i,1);
                             solver.add(j,0,j,1);
                         }
                         else {
                             solver.add(i,1,j,0);
                             solver.add(j,1,i,0);
                         }
                   }
                   else {
                        if (mat[i][j]&1) {
                             solver.add(i,0,j,1);
                             solver.add(i,1,j,0);
                             solver.add(j,0,i,1);
                             solver.add(j,1,i,0);
                        }
                        else {
                             solver.add(i,0,j,0);
                             solver.add(i,1,j,1);
                             solver.add(j,0,i,0);
                             solver.add(j,1,i,1);
                        }
                   }
                   mat[i][j]>>=1;
              }
           }
           flag = solver.solve();
           if (flag == 0) break;
       }

       if (!flag) printf("NO\n"); else printf("YES\n");

    }
    return 0;
}


HDU1815 - K题

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

const int INF = 1e7;
const int maxn = 510;
const int maxm = 1000+10;
struct TwoSAT{
   int n;
   int S[maxn*2],c;
   bool mark[maxn*2];
   vector<int> G[maxn*2];

   void init(int n) {
      this->n = n;
      memset(mark,0,sizeof(mark));
      for (int i=0; i<n*2; i++) G[i].clear();
   }

   void add(int x, int xval, int y, int yval) {
        x = x*2 + xval;
        y = y*2 + yval;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
   }

   bool dfs(int x) {
      if (mark[x^1]) return 0;
      if (mark[x]) return 1;
      mark[x] = 1;
      S[c++] = x;

      for (int i=0; i<G[x].size(); i++)
        if (!dfs(G[x][i])) return 0;
      return 1;
   }

   bool solve() {
      for (int i=0; i<n*2; i+=2)
         if (!mark[i] && !mark[i+1]) {
            c = 0;
            if (!dfs(i)) {
                while (c>0) mark[S[--c]] = 0;
                if (!dfs(i+1)) return 0;
            }
       }
      return 1;
   }

}solver;

int n,A,B;
struct Point {
   int x,y;
};
Point s1,s2;
Point p[maxn];

struct Edge{
   int u,v;
   Edge (int u=0, int v=0): u(u), v(v) {}
};
Edge hate[maxm],like[maxm];

int d1[maxn],d2[maxn],Len;
inline int Length(Point a, Point b) {
   return abs(a.x-b.x) + abs(a.y-b.y);
}

void build(int mid){
   for (int i=0; i<A; i++) solver.add(hate[i].u,0,hate[i].v,0), solver.add(hate[i].u,1,hate[i].v,1);
   for (int i=0; i<B; i++) solver.add(like[i].u,1,like[i].v,0), solver.add(like[i].u,0,like[i].v,1);
   for (int i=0; i<n; i++) {
      for (int j=i+1; j<n; j++) {
          if (d1[i]+d1[j]>mid) solver.G[i*2].push_back(j*2+1), solver.G[j*2].push_back(i*2+1);
          if (d2[i]+d2[j]>mid) solver.G[i*2+1].push_back(j*2), solver.G[j*2+1].push_back(i*2);
          if (d1[i]+Len+d2[j]>mid) solver.G[i*2].push_back(j*2), solver.G[j*2+1].push_back(i*2+1);
          if (d2[i]+Len+d1[j]>mid) solver.G[i*2+1].push_back(j*2+1), solver.G[j*2].push_back(i*2);
      }
   }
}

int main(){
    while (scanf("%d%d%d",&n,&A,&B)==3) {
        scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y);
        Len = Length(s1,s2);
        for (int i=0; i<n; i++) scanf("%d%d",&p[i].x,&p[i].y);
        for (int i=0; i<n; i++) d1[i] = Length(p[i],s1), d2[i] = Length(p[i],s2);
        int u,v;
        for (int i=0; i<A; i++) {
            scanf("%d%d",&u,&v);
            u--; v--;
            hate[i] = Edge(u,v);
        }
        for (int i=0; i<B; i++) {
            scanf("%d%d",&u,&v);
            u--; v--;
            like[i] = Edge(u,v);
        }

        int left = 0, right = INF;
        int mid, ans = -1;
        while (left<=right) {
            mid = (left+right)>>1;
            solver.init(n);
            build(mid);
            if (solver.solve()) {right = mid-1; ans = mid;}
            else left = mid+1;
        }

        printf("%d\n",ans);
    }
    return 0;
}





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值