Poj P3678 Katu Puzzle___2-SAT

版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/80385489

题目大意:

给出N个点,M条边,
每条边给出A,B,C,op
要求任意一条边满足A op B = C
opORAND, XOR中一个

1 ≤ N ≤ 1000
0 ≤ M ≤ 1,000,000

分析:

因为每个点的情况仅为01
所以设i为点i0的情况,i为点i1的情况

i and j=0
其中一点选1时,另一点必定要选0
则连边
i>jj>i

i and j=1
显然i,j都要选1
则连边i>ij>j

i or j=1
其中一点选0时,另外一点必定要选1
则连边
i>jj>i

i or j=0
显然i,j都要选0
则连边
i>ij>j

i xor j=1
显然满足i,j两点不同即可
连边
i>j i>j
j>ij>i

i xor j=0
显然满足i,j亮点相同即可
连边
i>ji>j
j>ij>i
然后就是一个2-SAT的模型
通过判断是否存在一组i,i在同一个强连通分量来判断是否有解即可

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define INF 2333333
#define M 1200005
#define N 2005

using namespace std;

struct node {
    int u, v, next;
}a[M];

int Ls[N], Belong[N], order[N], tot, cnt, n, m;
char str[10];
bool vis[N];

void addedge(int u, int v) {
    cnt++; 
    a[cnt].u = u;
    a[cnt].v = v;
    a[cnt].next = Ls[u];
    Ls[u] = cnt;
}

void dfs(int x, int times) {
    vis[x] = 1;
    for (int i = Ls[x]; i; i = a[i].next) 
         if (!vis[a[i].v]) dfs(a[i].v, times);
    if (!times) {
         tot++;
         order[tot] = x;
    } else Belong[x] = tot;
}

void Kosaraju() {
    for (int i = 1; i <= 2 * n; i++) vis[i] = 0;
    tot = 0;
    for (int i = 1; i <= 2 * n; i++) 
         if (!vis[i]) dfs(i, 0);

    int rp = cnt; cnt = 0;
    for (int i = 1; i <= 2 * n; i++) Ls[i] = 0;
    for (int i = 1; i <= rp; i++) addedge(a[i].v, a[i].u);

    for (int i = 1; i <= 2 * n; i++) vis[i] = 0;
    tot = 0;
    for (int i = 2 * n; i >= 1; i--) {
         int j = order[i];
         if (!vis[j]) {
             tot++;
             dfs(j, 1);
         }
    }
}

int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d %d %d %s", &u, &v, &w, str);
        u++, v++;
        if (strcmp(str, "OR") == 0) {
            if (w == 1) {
                addedge(u, v + n);
                addedge(v, u + n);
            } else {
                addedge(u + n, u);
                addedge(v + n, v);
            }
        }

        if (strcmp(str, "AND") == 0) {
            if (w == 1) {
                addedge(u, u + n);
                addedge(v, v + n);
            } else {
                addedge(u + n, v);
                addedge(v + n, u);
            }
        }

        if (strcmp(str, "XOR") == 0) {
            if (w == 1)
            {
                addedge(u, v + n);
                addedge(u + n, v);
                addedge(v, u + n);
                addedge(v + n, u);
            } else {
                addedge(u, v);
                addedge(v, u);
                addedge(u + n, v + n);
                addedge(v + n, u + n);
            }
        }
    }
    Kosaraju();
    bool check = 1;
    for (int i = 1; i <= n; i++) 
         if (Belong[i] == Belong [i+n]) check = 0;
    if (check) printf("YES\n");
          else printf("NO\n");
    return 0;
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页