CNF 2

'In Boolean logic, a formula is in conjunctive normal form (CNF) or clausal normal form if it is a conjunction of clauses, where a clause is a disjunction of literals' (cited from https://en.wikipedia.org/wiki/Conjunctive_normal_form)

In the other words, CNF is a formula of type , where & represents a logical "AND" (conjunction), represents a logical "OR" (disjunction), and vij are some boolean variables or their negations. Each statement in brackets is called a clause, and vij are called literals.

You are given a CNF containing variables x1, ..., xm and their negations. We know that each variable occurs in at most two clauses (with negation and without negation in total). Your task is to determine whether this CNF is satisfiable, that is, whether there are such values of variables where the CNF value is true. If CNF is satisfiable, then you also need to determine the values of the variables at which the CNF is true.

It is guaranteed that each variable occurs at most once in each clause.

Input

The first line contains integers n and m (1 ≤ n, m ≤ 2·105) — the number of clauses and the number variables, correspondingly.

Next n lines contain the descriptions of each clause. The i-th line first contains first number ki (ki ≥ 1) — the number of literals in the i-th clauses. Then follow space-separated literals vij (1 ≤ |vij| ≤ m). A literal that corresponds to vij is x|vij| either with negation, if vij is negative, or without negation otherwise.

Output

If CNF is not satisfiable, print a single line "NO" (without the quotes), otherwise print two strings: string "YES" (without the quotes), and then a string of m numbers zero or one — the values of variables in satisfying assignment in the order from x1 to xm.

一开始想成了网络流或者二分图匹配,但是增广的时间复杂度太高了。

不过方法是类似的,首先,如果一个变量只出现一种形式,那么就让这个变量出现过的clause为真

,这些变量和对应的clause就可以排除了。如果一个变量出现了两次,那么就把变量var看成是一条边,把clasue看成是一个点

在出现!var的clause U和出现var的clause V直接连一条边,选择var的值就转化成了决定边的方向

规定一个clasue有至少一个入边的时候表示clause为真。贪心,之前已经排除掉的clasue U中出现的还没有决定的变量var都可以当作是对U为假,

那么出现!var的V就全部为真了,这些V也可以排除了,所以可以用bfs或dfs完成这个过程。这是一个连通分量的情况。

对于还没有考虑过的连通分量,如果是一颗树,那么一定不行,因为每次删除只有一条入边的叶子,最后一个会剩下一个点无法使它为真。

是树即无环,因此用dfs找环,如果找到,那么将环中点删去,更新答案,重复bfs增广一个连通分量的操作。如果没找到,那么就输出NO。

因为var和clasue最多被标记一次所以时间复杂是O(n+m)。线性复杂度都跑了405ms,网络流或者二分图匹配怎么可能不T

#include<bits/stdc++.h>
using namespace std; const int maxn = 2e5+; #define PB push_back
vector<int> adj[maxn][];
vector<int> G[maxn],id[maxn];
char ans[maxn];
bool ok[maxn]; int n,m; queue<int> q; #define Add(x)\
ok[x] = true;\
q.push(x) void bfs()
{
while(q.size()){
int u = q.front(); q.pop();
for(int i = , M = G[u].size(); i < M; i++){
int v = G[u][i];
if(ok[v]) continue;
Add(v);
int var = id[u][i];
ans[var] = (v == adj[var][][])+'';
}
}
} bool vis[maxn];
bool dfs(int u,int pvar)
{
if(vis[u]) return true;
vis[u] = true;
for(int i = , M = G[u].size(); i < M; i++){
int v = G[u][i];
int var = id[u][i];
if(var == pvar) continue;
if(dfs(v,var)){
Add(u);
ans[var] = (u == adj[var][][])+'';
return true;
}
}
return false;
} int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i = ; i < n; i++){
int k; scanf("%d",&k);
int v;
while(k--){
scanf("%d",&v);
int fg = v;
if(v<) v = -v;
adj[--v][fg>].PB(i);
}
} for(int i = ; i < m; i++){
if(adj[i][].empty()){
for(int j = ,M = adj[i][].size(); j < M; j++) {
Add(adj[i][][j]);
}
ans[i] = '';
}else if(adj[i][].empty()){
for(int j = ,M = adj[i][].size(); j < M; j++) {
Add(adj[i][][j]);
}
ans[i] = '';
}else {
int u = adj[i][][], v = adj[i][][];
G[u].PB(v); id[u].PB(i);
G[v].PB(u); id[v].PB(i);
}
}
for(int i = ; i < n; i++){
bfs();
if(ok[i]) continue;
if(!dfs(i,-)){
puts("NO");
return ;
}
} puts("YES");
for(int i = ; i < m; i++){
if(ans[i]) putchar(ans[i]);
else putchar('');
}
return ;
}

Codeforces Round #317 div2 E div1 C CNF 2 (图论,匹配)的更多相关文章

  1. Codeforces Round #539 div2

    Codeforces Round #539 div2 abstract I 离散化三连 sort(pos.begin(), pos.end()); pos.erase(unique(pos.begin ...

  2. 【前行】◇第3站◇ Codeforces Round #512 Div2

    [第3站]Codeforces Round #512 Div2 第三题莫名卡半天……一堆细节没处理,改一个发现还有一个……然后就炸了,罚了一啪啦时间 Rating又掉了……但是没什么,比上一次好多了: ...

  3. Codeforces Round#320 Div2 解题报告

    Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Fin ...

  4. Codeforces Round #564(div2)

    Codeforces Round #564(div2) 本来以为是送分场,结果成了送命场. 菜是原罪 A SB题,上来读不懂题就交WA了一发,代码就不粘了 B 简单构造 很明显,\(n*n\)的矩阵可 ...

  5. Codeforces Round #361 div2

    ProblemA(Codeforces Round 689A): 题意: 给一个手势, 问这个手势是否是唯一. 思路: 暴力, 模拟将这个手势上下左右移动一次看是否还在键盘上即可. 代码: #incl ...

  6. Codeforces Round #626 Div2 D,E

    比赛链接: Codeforces Round #626 (Div. 2, based on Moscow Open Olympiad in Informatics) D.Present 题意: 给定大 ...

  7. CodeForces Round 192 Div2

    This is the first time I took part in Codeforces Competition.The only felt is that my IQ was contemp ...

  8. CodeForces Round #250 Div2

    A. The Child and Homework 注意仔细读题,WA了好多次,=_= #include <cstdio> #include <cstring> #includ ...

  9. Codeforces Round #359 div2

    Problem_A(CodeForces 686A): 题意: \[ 有n个输入, +\space d_i代表冰淇淋数目增加d_i个, -\space d_i表示某个孩纸需要d_i个, 如果你现在手里 ...

随机推荐

  1. 1.1- 1.2 hive入门

    一.hive是什么 由Facebook开源用于解决海量结构化日志的数据统计: Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射成一张表, 并提供类SQL查询功能: 构建在Had ...

  2. c++函数模板二栈实现

    1 没有使用模板的栈实现 #include <iostream> #include <string> using namespace std; class Stack { pu ...

  3. Subresource Integrity(子资源一致性)和JS DDos 攻击

    以下文章转载自 http://www.cnblogs.com/zoucaitou/p/4505483.html 和 http://www.puronglong.com/blog//2015/04/12 ...

  4. python 内置函数的补充 isinstance,issubclass, hasattr ,getattr, setattr, delattr,str,del 用法,以及元类

    isinstance   是 python中的内置函数 , isinstance()用来判断一个函数是不是一个类型 issubclass  是python 中的内置函数,  用来一个类A是不是另外一个 ...

  5. java 关于getProperty()方法中反斜杠问题

    问: 在配置文件a.properties中有一行path=C:\test在java中getProperty("path")后,java把\t认为是一个字符TAB.怎样才能取到正确的 ...

  6. QDUOJ LC的课后辅导 单调递增栈

    LC的课后辅导 发布时间: 2015年9月19日 21:42   时间限制: 1000ms   内存限制: 256M 描述 有一天,LC给我们出了一道题,如图: 这个图形从左到右由若干个 宽为1 高不 ...

  7. 死磕 java同步系列之volatile解析

    问题 (1)volatile是如何保证可见性的? (2)volatile是如何禁止重排序的? (3)volatile的实现原理? (4)volatile的缺陷? 简介 volatile可以说是Java ...

  8. hdu5861【线段树】

    题意: 有n个点,每个两两之间有一条路,给出每条路开放的花费,每条路只能打开关闭一次,然后m天里给出一个区间代表这条路必须在该天开放,求每天需要的花费. 思路: 这是一题纯粹用线段树搞的题. 我们可以 ...

  9. HDU5113【DFS+剪枝】

    题意: n*m的矩阵 k种颜色 每种颜色有c[i]个 上下左右相邻的格子不能一样的颜色 问你有没有一种染色方法,有的话输出方案. 思路: 暴搜啊,n,m都才5,做完以后大哥的剪枝是奇偶剪枝,其实画完图 ...

  10. adb server version (39) doesn't match this client (40); killing...

    在启动RN项目的时候也报错,上面的错误是在adb的环境变量中的位置和android studio的sdk不是一个位置.adb是在sdk中的,所以他们应该是一致的位置 android studio的sd ...