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

告别手册!S32K3XX的eMIOS实战:从GPT定时到PWM输出,一个通道搞定电机控制 本文深入探讨了NXP S32K3XX系列MCU的eMIOS模块在电机控制中的高效应用。通过单通道实现PWM生成、输入捕获和定时中断三大功能,展示了如何简化BLDC电机控制硬件设计。文章结合RTD库与寄存器级编程,提供动态模式切换和性能优化方案,显著降低CPU负载。 阅读详情

寒假回老家那几天,看了蓝书的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;
}





[ATF]-smc指令详解 1、在ree/tee调用smc之前 2、调用smc之后,cpu触发同步异常,进入ATF的sync_exception_aarch64—>handle_sync_exception—>smc_handler64处理函数 在smc_handler64中又调用了smc_handler func smc_handler64 /* ---------------------------------------------- * Detect if this is a RUN_IMAGE or ot 阅读详情

相关推荐

ABAP动态填充Word模板:基于cl_docx_document的XML替换方案

本文详细介绍了ABAP中基于cl_docx_document类的动态Word模板填充方案。该方案通过直接操作DOCX文件的XML核心,完美解决了传统OLE/DOI方法在格式保真、性能和后台运行方面的痛点,是实现复杂、批量Word文档生成的优雅解决方案。

gpt4scribbler的博客 525

2-sat-总结+例题

https://www.cnblogs.com/31415926535x/p/10644419.html 从寒假就开始准备学2sat,,然后当时了解了一下模板就溜了,,,一直到上个星期,,三月底才好好重新的看一下,,,做了一些题,,感觉大致的了解了2sat的基本套路,,一般的题都是在建图做文章,,这题出现的频率貌似也不高,,,之后就放一放吧,,,啥时候忘记了就翻出来看一看,,嘿嘿 概述 2-sat...

weixin_30502157的博客 781

AFSim 2.9实战指南:从入门到精通的中文教程

本文是AFSim 2.9的实战中文教程,旨在帮助用户从零开始掌握这一先进的仿真框架。内容涵盖从环境安装、运行第一个“Hello World”仿真,到深入理解实体、组件、想定编辑器等核心概念,并进阶探讨动力学建模、传感器仿真与红蓝对抗想定构建。最后,指南还提供了效能分析与实战排错技巧,帮助用户将仿真结果转化为有价值的量化数据,适用于军事、航空航天等领域的复杂系统行为模拟研究。

weixin_29294395的博客 355

2-SAT讲解+模板

一、定义 要知道2-sat是什么我们先要知道什么是适定性问题(Satisfiability)。适定性问题通俗的来说就是确定是否可以满足所有条件,或者说就是确定一个满足所有条件的方案。取英文的前三个字母,简称sat问题。 通俗的sat问题表述一般是这样的:有很多个集合,每个集合里面有若干元素,现给出一些取元素的规则,要你判断是否可行,可行则给出一个可行方案。如果所有集合中,元素个数最多的集合有k个,...

Waiting For You 538

容器内存黑洞排查手册:当PageCache让你的Pod莫名被OOM时

本文深入剖析了容器环境中因Linux内核PageCache机制导致Pod被OOM Killer终止的“内存黑洞”问题。文章解释了Kubernetes基于Working Set内存指标进行OOM判断的逻辑,揭示了传统监控工具与cgroup统计的差异,并通过典型场景分析、实战诊断工具和优化策略,提供了从问题定位到系统调优的完整解决方案。

weixin_29294975的博客 221

Amesim基础篇-元件详解-流体库管路

Amesim基础篇-元件详解-流体库管路

2201_75375391的博客 4519

学习笔记(two sat)

关于two sat算法 两篇很好的论文由对称性解2-SAT问题(伍昱), 赵爽 2-sat解法浅析(pdf)。 一些题目的题解 poj 3207 poj 3678 poj 3683 poj 3648 poj 2723 poj 2749 关于具体算法 首先此算法只对于存在类似于一个点选了另一个点就不能选这样的条件,并且每个点只有两种状态(一般是选或不选),不然是个NP问题 大体做法就是先转换模...

weixin_30262255的博客 356

Go语言爬虫:chromedp 的详细使用

chromedp 是 Go 语言中无头浏览器自动化的终极利器。它能驱动真实的 Chrome 浏览器,处理 JavaScript 渲染、复杂交互和反爬虫机制

数据知道的博客 4492

TWO-SAT题目总结

最小字典序输出 题意: 现在有n个党派,每个党派有2个代表,我们需要从每个党派中选一个代表出来,构成一个n个人的立法委员会.但是可能有一些代表互相讨厌,所以他们不能同时出现在立法委员会中.现在问你是否存在一个合理的方案,且输出所有可能立法委员会的最小字典序结果. 分析: 要输出最小字典序的2-SAT问题,用刘汝佳 训练指南上的方法是最简单的(即按...

lanshan1111的博客 425

以太网_RGMII接口与GMII接口的转化_03

RGMII接口转GMII接口!

weixin_42499230的博客 378

华为OD机试真题2026双机位C卷 C语言 实现【主次关联成环警告】

在ICT运维领域,现网运维工程师面向对设备上报的众多告警,往往需要筛选出最主要的告警优先处理,次等级的告警或许为同一个根因导致的告警,处理优先级会放后或者不处理,这样就诞生出主次关联告警的概念。给定一系列告警的主次关联关系,判断是否存在如下情况:

MISAYAONE的博客 172

AC是什么意思?

AC就是accept,接受的意思,一般用在ONLINE JUDGE网上,表示能通过的代码。在刷算法题时,我们有时会接触一些“黑话”,类似上图。那么它们都是什么意思呢?(注:以下内容为从北京航空航天大学AC编程平台。常见的是AC、WA、TLE。

rt_tryqc的博客 6479

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

关于2-SAT

关于2-SAT有两种模板 第一种用到了tarjan缩点 第二种则是dfs(可以实现字典序最小) 关于什么是2-SAT,先不介绍,看下这道模板题。 模板题链接 可以看到,我们需要找到一个合理的选择,使得所有被选择的都不会发生冲突。下面以id+m代表第id号家庭的丈夫,id+w代表第id号家庭的妻子。如1m代表一号家庭的丈夫。 如果1m和2w有矛盾,那么: 1.如果我们要选择1m,就不能选用2w 反过来说如果我们选择1m,就必须选用2m (因为一个家庭必须选择一人) 2.同样如果选择了2w,那么必须选用1w 基

weixin_43353639的博客 186

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

2-Sat

2-Sat 算法 简介 什么是2-SAT呢?就是有一些集合,每个集合中有且仅有两个元素,同时每个集合需要选择一个作为代表,集合间的元素存在一定的选择关系,求解可行性及可行方案。 关键:连边 2-SAT算法本身并不难,关键是连边,不过只需要充分理解好边的概念:a->b即选a必选b。 (也即连单向边) a、b不能同时选:选了a就要选b’,选了b就要选a’。 a、b必须同时选:选了a就要选b,选...

UniverseofHK的博客 404

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

P4782 【模板】2-SAT 问题

百紫斩第8天\color{purple}百紫斩第8天百紫斩第8天 原题传送门 题目大意 有 nnn 个布尔变量 x1∼xnx_1\sim x_nx1​∼xn​,另有 mmm 个需要满足的条件,每个条件的形式都是 「xix_ixi​ 为 true / false 或 xjx_jxj​ 为 true / false」。 比如 「x1x_1x1​ 为真或 x3x_3x3​ 为假」、「x7x_7x7​ 为假或 x2x_2x2​ 为假」。 2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。 解题思路 2-S

orz 160

【 HDU - 3062】Party(2-sat)

题干: 有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席? Input n: 表示有n对夫妻被邀请 (n<= 1000) m: 表示有m 对矛盾关系 ( m < (n - 1) * (n -1)) 在接下来的m行...

xuanweiace的博客 598

(转)2-sat 专题

【2-sat】专题~ 2-sat是一个逻辑性很强的算法,但是其套路比较固定,所以不是很热,题目很少,但也不乏AC后让人大呼爽快的好题,下面放出两篇极品论文还有几道题目的题解以供交流~~ 2-sat学习: 对称性解决2-sat的ppt 赵爽的2-SAT解法浅析论文 强连通判是否存在解: HDU 3062Party [入门] 2-sat入门题,建图后求强连...

weixin_30266829的博客 115

POJ 3678 Katu Puzzle 【经典2-SAT】

传送门:POJ 3678 Katu Puzzle Time Limit: 1000MS Memory Limit: 65536K Problem Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a boolean operator op (...

Waiting For You 248

【2-sat】专题~

2-sat是一个逻辑性很强的算法,但是其套路比较固定,所以不是很热,题目很少,但也不乏AC后让人大呼爽快的好题,下面放出两篇极品论文还有几道题目的题解以供交流~~ 2-sat学习: 对称性解决2-sat的ppt 赵爽的2-SAT解法浅析论文 强连通判是否存在解: HDU 3062Party [入门] 2-sat入门题,建图后求强连通判断是否有解即可 View C...

weixin_30408739的博客 156

[BZOJ4945][NOI2017]游戏(2-SAT)

[NOI2017][BZOJ4945]游戏(2-SAT)题目见http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf 可以发现,除了x地图之外,其余的地图只适合两种赛车。而在这里,我们先假设所有的地图都适合且只适合两种赛车,这样就是2−SAT2-SAT裸题了。 对于每场游戏用两个点ii和i′i',分别表示第ii场游戏使用该地图适合的第一种赛车和

女装的你,如此好看! 1708

JSOI2010 满汉全席 【2-SAT】

传送门:题目链接 满汉全席 题目描述 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中。由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉全席,而能够烹饪出经过专家认证的满汉全席,也是中国厨师最大的荣誉之一。世界满汉全席协会是由能够料理满汉全席的专家厨师们所组成,而他们之间还细分为许多不同等级的厨师。 为了招收新进的厨师进...

Waiting For You 256

【2-SAT问题】解题报告:POJ 3678 Katu Puzzle(2-SAT问题的判定)

每个元素只有两种可能的取值,所以是2-SAT的模型. 我们建立2*n个点,x∈[1…n]表示x取0,x∈[n+1…n+n]表示x取1 考虑将所给的关系转化为有向边. u and v=1:u,v都必须是1.为了让他们都是1,我们需要让他们为0时出现矛盾,也就是加边(u,u+n),(v,v+n) u and v=0:如果u=1那么v=0,加边(u+n,v).同理,加边(v+n,u) u or v=1:如果u=0那么v=1加边(u,v+n).同理,加边(v,u+n) u or v=0:u,v都必须是0.为了让.

繁凡さん的博客 566

POJ 2296 Map Labeler 2-SAT+二分答案

这是我的第一篇博文,OI省选翻车几乎爆零,于是从OI狗变成了ACMer 听前辈说多写题解、模板、心得丢博客里会有明显的进步,于是决定开始这么做了。 想着第一篇是要写题解还是要写模板,想了想还是写题解。一道比较简单的题。 题目链接:http://poj.org/problem?id=2296 题目大意:地图上有很多的城市,每个城市需要贴上一个标签,标签是正方形,而且标签的上边

foreyes_1001的博客 685

HDU3062 - 2-sat

Party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6168    Accepted Submission(s): 2013 Problem Description 有n对夫妻被邀请参加一个聚会,因为场地的

Code-Dreamer的博客 1453

POJ2723 2-SAT+二分

一对钥匙里面二选一,又是一个很明显的2-SAT问题特征。 分点: 一把钥匙根据选不选分为两点,n把钥匙就是2n个点 建边: 首先根据给定的钥匙进行建边,选了其中一个另一个就不能选。 然后二分,枚举通过门的数量k,建边建到第k个门过,门上的钥匙必须要有一把,因此建边的根据是一个钥匙不选那么另一个就一定要选。 AC代码 由于前面两道例题的模板和这个一样,注释就不写了,如有疑问请参考 2-SAT简介 //AC 64MS //2021/10/09 #include <iostream> #include

Shanhj的博客 163

POJ2296题解 2-SAT+二分

题目链接 每个城市都要在lable边的中点处,且lable要么朝下,要么朝上,很明显的2-SAT问题特征。因为每个lable的边长都要相同,且范围给定,因此可以用二分进行枚举。 分点 i2表示i城市的lable朝下,i2+1表示i城市的lable朝上,一共2n个点 建边 根据枚举的lable长度length,有三种情况: 前提是两个城市的x相差小于length,不然怎么都不会影响 1.两个城市的y相同,那么必须是一上一下 2.两个城市的y相差小于length,必须是下面的城市朝下,上面的城市朝上 3.两个城

Shanhj的博客 195
上一篇: 2017ACM-ICPC北京区域现场赛 G题 hihocoder1633
下一篇: CERC2017 F: Faulty Factorial 简单数论题
罗侯
博客等级 码龄10年 135粉丝 258原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值