问一下建图思路

P4171 [JSOI2010] 满汉全席

天上一颗蛋 @ 2018-08-10 10:31:52

我是一种材料拆成四个点(分别用n * 4,n * 4 + 1, n * 4 + 2, n * 4 + 3代表汉式做,汉式不做,满式做,满式不做),对于同一种材料满足汉式满式二选一,(即 汉式 xor 满式 = 1,连边如下:)

for(int i = 1;i <= num;i++){
            int x = i * 2, y = i * 2 + 1;
            add(x << 1, y << 1 | 1, 1);
            add(y << 1, x << 1 | 1, 1);
            add(x << 1 | 1, y << 1, 1);
            add(y << 1 | 1, x << 1, 1);
            }

对于每个评委的要求满足两个至少选其一(即 要求1 or 要求2 = 1,连边如下)

for(int i = 1;i <= nr;i++){
            c = getchar();
            x = RD() * 2;
            if(c == 'm')x++;
            c = getchar();
            y = RD() * 2;
            if(c == 'm')y++;
            add(x << 1, y << 1 | 1, 1);
            add(y << 1, x << 1 | 1, 1);
            }

检查时若是一种材料同时做了满式和汉式(即col[做汗] = col[做满] ),或是一样菜同时要求做和不做(即 col[做] = col[不做] )则不合法,代码如下:

bool check(){
    for(int i = 1;i <= num;i++){
        int x = i << 1, y = i << 1 | 1;
        if(col[x << 1 | 1] == col[y << 1 | 1])return 0;
        }
    for(int i = 2;i <= (num << 1 | 1);i++){
        if(col[i << 1] == col[i << 1 | 1])return 0;
        }
    return 1;
    }

只有10分,查不出错了

附上全部代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
typedef long long LL;
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 2000019,INF = 1e9 + 19;
int head[maxn],nume = 1;
struct Node{
    int v,dis,nxt;
    }E[maxn << 2];
void add(int u,int v,int dis){
    E[++nume].nxt = head[u];
    E[nume].v = v;
    E[nume].dis = dis;
    head[u] = nume;
    }
int num, nr, T;
int DFN[maxn], LOW[maxn], INDEX;
int S[maxn], top;
bool ins[maxn];
int col[maxn], numc;
void Tarjan(int u){
    DFN[u] = LOW[u] = ++INDEX;
    S[++top] = u;ins[u] = 1;
    for(int i = head[u];i;i = E[i].nxt){
        int v = E[i].v;
        if(!DFN[v])Tarjan(v), LOW[u] = min(LOW[u], LOW[v]);
        else if(ins[v])LOW[u] = min(LOW[u], DFN[v]);
        }
    if(DFN[u] == LOW[u]){
        numc++;
        while(S[top + 1] != u){
            col[S[top]] = numc;
            ins[S[top--]] = 0;
            }
        }
    }
void init(){
    memset(head, 0, sizeof(head));
    nume = 1;
    memset(DFN, 0, sizeof(DFN));
    memset(LOW, 0, sizeof(LOW));
    INDEX = 0;
    memset(col, 0, sizeof(col));
    numc = 0;
    }
bool check(){
    for(int i = 1;i <= num;i++){
        int x = i << 1, y = i << 1 | 1;
        if(col[x << 1 | 1] == col[y << 1 | 1])return 0;
        }
    for(int i = 2;i <= (num << 1 | 1);i++){
        if(col[i << 1] == col[i << 1 | 1])return 0;
        }
    return 1;
    }
int main(){
    T = RD();
    while(T--){
        init();
        num = RD();nr = RD();
        char c;int x, y;
        for(int i = 1;i <= nr;i++){
            c = getchar();
            x = RD() * 2;
            if(c == 'm')x++;
            c = getchar();
            y = RD() * 2;
            if(c == 'm')y++;
            add(x << 1, y << 1 | 1, 1);
            add(y << 1, x << 1 | 1, 1);
            }
        for(int i = 1;i <= num;i++){
            int x = i * 2, y = i * 2 + 1;
            add(x << 1, y << 1 | 1, 1);
            add(y << 1, x << 1 | 1, 1);
            add(x << 1 | 1, y << 1, 1);
            add(y << 1 | 1, x << 1, 1);
            }
        for(int i = 4;i <= (num << 2) + 3;i++)if(!DFN[i])Tarjan(i);
        if(check())puts("GOOD");
        else puts("BAD");
        }
    return 0;
    }

by Jameswood @ 2018-08-10 10:44:13

蒟蒻开始瑟瑟发抖


by niiick @ 2018-08-10 12:36:18

@天上一颗蛋

2-SAT怎么会要拆四个点你在想什么=_=


by 天上一颗蛋 @ 2018-08-10 14:19:49

@niiick 每个菜两个属性啊


by niiick @ 2018-08-10 14:28:37

@天上一颗蛋 拆四个点建边麻烦倍时间空间又翻倍

拆两个点不好吗=_=

不过你这里好像并没有看出什么问题(?)

会不会是读入编号的玄学字符错误(?)


by 天上一颗蛋 @ 2018-08-10 14:33:22

@niiick 不然我改改读入吧。。getchar有时候就是有点毒(真的没问题的吧)


by niiick @ 2018-08-10 14:37:35

@天上一颗蛋, 这里是不是有问题

add(x << 1, y << 1 | 1, 1);
add(y << 1, x << 1 | 1, 1);

x与y是或的关系

x作不代表y一定不做, 应该反过来y不做代表x一定要做


by niiick @ 2018-08-10 14:37:45

@天上一颗蛋


by 天上一颗蛋 @ 2018-08-10 15:09:15

已过, 读入的锅, 用了getchar最尼玛坑的是本地和在线IDE输出不一样


|