题意

给定一个有向图,问是否能够分成两个有向完全图。

思路

裸的2-sat……我们设一个完全图为0,另一个完全图为1,对于一个点对(u, v),如果u、v不是双向连通则它们两个不能在一组,即u和v至少又一个为0,至少又一个为1。则我们向2-sat中加条u->v', u'->v, v->u', u'->v的边,然后验证可行性即可。

(关于2-SAT的建图可以见这篇题解

代码

[cpp]
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, end) for (int i = begin; i <= end; i ++)
using namespace std;

const int MAXN = 2005;
const int MAXE = MAXN * MAXN;
bool map[105][105];
struct node{
int u, v;
int next;
}arc[MAXE];
int cnt, head[MAXN];
void init(){
cnt = 0;
MEM(head, -1);
return ;
}
void insert(int u, int v){
arc[cnt].u = u;
arc[cnt].v = v;
arc[cnt].next = head[u];
head[u] = cnt ++;
}
/* ---- Tarjan ---- */
int scc_num, scc[MAXN];
int dfn[MAXN], low[MAXN], id;
stack st;
bool vis[MAXN], instack[MAXN];
void dfs(int u){
vis[u] = instack[u] = 1;
st.push(u);
dfn[u] = low[u] = ++ id;
for (int i = head[u]; i != -1; i = arc[i].next){
int v = arc[i].v;
if (!vis[v]){
dfs(v);
low[u] = min(low[u], low[v]);
}
else if (instack[v]){
low[u] = min(low[u], dfn[v]);
}
}
if (low[u] == dfn[u]){
++ scc_num;
while(st.top() != u){
scc[st.top()] = scc_num;
instack[st.top()] = 0;
st.pop();
}
scc[st.top()] = scc_num;
instack[st.top()] = 0;
st.pop();
}
return ;
}
void tarjan(int n){
MEM(vis, 0);
MEM(instack, 0);
MEM(dfn, 0);
MEM(low, 0);
MEM(scc, 0);
id = scc_num = 0;
while(!st.empty())
st.pop();

for (int i = 1; i <= n; i ++){ //枚举节点
if (!vis[i])
dfs(i);
}
return ;
}
/* ---- Tarjan ---- */
int opp[MAXN]; //与i同组的标号i', 默认设为i+N;
void set_opp(int N){ //设定同组标号.
for (int i = 1; i <= N; i ++)
opp[i] = i + N;
return ;
}
//根据y约束向构图中加边,N表示组数.
//(通常一组表示一个布尔变量的0\1值, 但也有题目表示的是一组互斥约束的布尔值)
void add_clause(int N){
init();
set_opp(N);
for (int i = 1; i <= N; i ++){
for (int j = 1; j <= N; j ++){
if (i == j || (map[i][j] && map[j][i])) continue;
insert(i, opp[j]);
insert(opp[i], j);
insert(j, opp[i]);
insert(opp[j], i);
}
}
return ;
}
bool check(int N){ //2-SAT判定.N表示组数.opp[i]表示与i同互斥组的另一个点
tarjan(2*N);
for (int i = 1; i <= 2*N; i ++){
if (scc[i] == scc[opp[i]]){
return false;
}
}
return true;
}
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int n;
while(scanf("%d", &n) != EOF){
MEM(map, 0);
for (int i = 1; i <= n; i ++){
int tmp;
while(scanf("%d", &tmp), tmp){
map[i][tmp] = 1;
}
}
add_clause(n);
if (check(n)){
puts("YES");
}
else{
puts("NO");
}

}
return 0;
}
[/cpp]

HDU 4751 Divide Groups (2-SAT)的更多相关文章

  1. HDU 4751 Divide Groups (2013南京网络赛1004题,判断二分图)

    Divide Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  2. HDU 4751 Divide Groups 2013 ACM/ICPC Asia Regional Nanjing Online

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4751 题目大意:判断一堆人能否分成两组,组内人都互相认识. 解题思路:如果两个人不是相互认识,该两人之 ...

  3. hdu 4751 Divide Groups(dfs染色 或 2-sat)

    Problem Description   This year is the 60th anniversary of NJUST, and to make the celebration more c ...

  4. HDU 4751 Divide Groups

    题目链接 比赛时候,建图建错了.大体算法想到了,不过很多细节都没想好. #include <cstdio> #include <cstring> #include <cm ...

  5. hdu 4751 Divide Groups bfs (2013 ACM/ICPC Asia Regional Nanjing Online 1004)

    SDUST的训练赛 当时死磕这个水题3个小时,也无心去搞其他的 按照题意,转换成无向图,预处理去掉单向的边,然后判断剩下的图能否构成两个无向完全图(ps一个完全图也行或是一个完全图+一个孤点) 代码是 ...

  6. HDOJ 4751 Divide Groups

    染色判断二分图+补图 比赛的时候题意居然是反的,看了半天样例都看不懂 .... Divide Groups Time Limit: 2000/1000 MS (Java/Others)    Memo ...

  7. Hdu 4751(2-SAT)

    题目链接 Divide Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  8. HDU 5783 Divide the Sequence(数列划分)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  9. uva 10004 Bicoloring(dfs二分染色,和hdu 4751代码差不多)

    Description In the ``Four Color Map Theorem" was proven with the assistance of a computer. This ...

随机推荐

  1. php5.6 的curl开启和之前的不太一样了,搞了半天,记录下

    设置电脑环境变量中的->系统变量(注:不是用户变量) 新建 PHP_HOME 值 D:\php /PHP 根目录 Path 增加 ;%PHP_HOME%;%PHP_HOME%\ext       ...

  2. Instagram的技术探索(转)

    add by zhj: 略有修改 原文:http://www.cnblogs.com/xiekeli/archive/2012/05/28/2520770.html 前一篇翻译了Instagram b ...

  3. pandas 取消读取csv时默认第一行为列名

    读取时默认第一行为列名 此时DataFrame的列名为第一行数据: 因为第一行为有效数据,故不可作为列名,要么重新起列名,要么使用默认序列列名: 取消默认第一行为列名 给 pd.read_csv() ...

  4. pathmunge

    pathmunge是linux系统redhat系列版本系统变量/etc/profile中的函数 判断当前系统的PATH中是否有该命令的目录,如果没有,则判断是要将该目录放于PATH之前还是之后 pat ...

  5. (2.4)DDL增强功能-数据汇总grouping、rollup、cube

    参考:https://www.cnblogs.com/nikyxxx/archive/2012/11/27/2791001.html 1.rollup (1)rollup在group by 子句中使用 ...

  6. eclipse怎么导出可执行jar包

    在eclpse中找到你要导出的java程序 选中它 单击文件 -->export 在弹出的export对话框中找到 jar File 单击选中-->next 按图示顺序依次 选好你的jav ...

  7. js-jquery-从SweetAlert到SweetAlert2

    原文地址:https://github.com/limonte/sweetalert2/wiki/Migration-from-SweetAlert-to-SweetAlert2 1. IE supp ...

  8. ThinkPhp3.2.3 多项目 后台 APP接口设计 框架设计

    ↓↓↓项目文件组成部分↓↓↓ APP文件是后台,index.php是入口文件 Interface文件是接口,注意这里不要用api命名!可能会有问题!interface.php是入口文件 注:两个入口文 ...

  9. Linux下编译安装MySQL5.6

    [准备工作] 所有操作需要在root用户下 本机测试案例系统信息:centos7.3 安装路径:/usr/local/mysql [安装MySQL] 先安装如下依赖包: $ yum -y instal ...

  10. ruby中的预定义变量(Predifined Variables)