CF1971H ±1

传送门

题目条件转换为,三个值不能有两个同时为负数。

\(x,-x\) 看作 \(x,\lnot x\),条件就变成了 \((x \land y) \lor (x \land z) \lor (y \land z)\)

这个形式显然是 \(2-sat\),代码很好写。

#include<bits/stdc++.h>
using namespace std;

const int N = 2e6 + 7;

int v[4][N];
vector<int> g[N];
int n;
void add(int a, int b) {
    int k1, k2;
    if(a > 0) k1 = 1;
    else k1 = 0;
    if(b > 0) k2 = 1;
    else k2 = 0;
    a = abs(a);
    b = abs(b);
    if(k1 && k2){
        g[a + n].push_back(b);
        g[b + n].push_back(a);
	}
	else if(!k1 && k2){
        g[a].push_back(b);
        g[b + n].push_back(a + n);
	}
	else if(k1 && !k2){
        g[a + n].push_back(b + n);
        g[b].push_back(a);
	}
	else if(!k1 && !k2){
        g[a].push_back(b + n);
        g[b].push_back(a + n);
	}
}
int col[N], scc[N], dfn[N], low[N], vis[N];
int scccnt, dfncnt, stk[N], top;
void tarjan(int u) {
    low[u] = dfn[u] = ++ dfncnt;
    stk[++ top] = u;
    vis[u] = 1;
    for(auto v : g[u]) {
        if(!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(vis[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]) {
        int y;
        scccnt ++;
        do {
            y = stk[top --];
            vis[y] = 0;
            col[y] = scccnt;
        }while(y != u);
    }
}

void init() {
    for(int i = 0; i <= 2 * n + 10; i ++) {
        low[i] = dfn[i] = col[i] = vis[i] = stk[i] = 0;
    }
    top = 0;
    scccnt = 0;
    dfncnt = 0;
    for(int i = 0; i <= 2 * n; i ++) g[i].clear();
}
void solve() {
    
    
    cin >> n;

    init();
    for(int i = 1; i <= 3; i ++) {
        for(int j = 1; j <= n; j ++) {
            cin >> v[i][j];
        }
    }
    for(int i = 1; i <= n; i ++) {
        int x = v[1][i], y = v[2][i], z = v[3][i];
        add(x, y);
        add(x, z);
        add(y, z);
    }   
    for(int i = 1; i <= n * 2; i ++) {
        if(!dfn[i]) tarjan(i);
    }
     for(int i = 1; i <= n; i ++){
    	if(col[i] == col[i + n]){
    		cout << "No" << endl;
    		return ;
    	}
    }
    cout << "Yes" << endl;
}
int main() {
    int T;
    cin >> T;
    while(T --) solve();
    return 0;
}
posted @ 2024-05-14 00:51  你说得太对辣  阅读(1)  评论(0编辑  收藏  举报