HDU 4751 Divide Groups (2-SAT)
题意
给定一个有向图,问是否能够分成两个有向完全图。
思路
裸的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)的更多相关文章
- HDU 4751 Divide Groups (2013南京网络赛1004题,判断二分图)
Divide Groups Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- HDU 4751 Divide Groups 2013 ACM/ICPC Asia Regional Nanjing Online
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4751 题目大意:判断一堆人能否分成两组,组内人都互相认识. 解题思路:如果两个人不是相互认识,该两人之 ...
- hdu 4751 Divide Groups(dfs染色 或 2-sat)
Problem Description This year is the 60th anniversary of NJUST, and to make the celebration more c ...
- HDU 4751 Divide Groups
题目链接 比赛时候,建图建错了.大体算法想到了,不过很多细节都没想好. #include <cstdio> #include <cstring> #include <cm ...
- hdu 4751 Divide Groups bfs (2013 ACM/ICPC Asia Regional Nanjing Online 1004)
SDUST的训练赛 当时死磕这个水题3个小时,也无心去搞其他的 按照题意,转换成无向图,预处理去掉单向的边,然后判断剩下的图能否构成两个无向完全图(ps一个完全图也行或是一个完全图+一个孤点) 代码是 ...
- HDOJ 4751 Divide Groups
染色判断二分图+补图 比赛的时候题意居然是反的,看了半天样例都看不懂 .... Divide Groups Time Limit: 2000/1000 MS (Java/Others) Memo ...
- Hdu 4751(2-SAT)
题目链接 Divide Groups Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- HDU 5783 Divide the Sequence(数列划分)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- uva 10004 Bicoloring(dfs二分染色,和hdu 4751代码差不多)
Description In the ``Four Color Map Theorem" was proven with the assistance of a computer. This ...
随机推荐
- Spark集群安装和WordCount编写
一.Spark概述 官网:http://spark.apache.org/ Apache Spark™是用于大规模数据处理的统一分析引擎. 为大数据处理而设计的快速通用的计算引擎. Spark加州大学 ...
- CF909F AND-permutations 构造
正解:构造 解题报告: 传送门! QAQ我jio得还挺难的,,,构造+数论什么的果然还是不适合灵巧这种菜菜啊QAQ 不过理解了的话也就没有那么难?所以还是港下QAQ 首先看task1 首先要发现一个, ...
- editplus的常用快捷键
小编给大家整理了一些软件的快捷键.http://www.downza.cn/soft/187814.html 创建当前行的副本:Ctrl+J 反转选定文本的大小写:Ctrl+K 选择当前行:Ctrl+ ...
- android 百度地图 No implementation found for int
java.lang.UnsatisfiedLinkError: No implementation found for int com.baidu.platform.comjni.map.common ...
- centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 访问控制 apache rewrite 配置开机启动apache tcpdump 第二十节课
centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 ...
- Java-idea-运行tomcat 报內存溢出 PermGen space
错误:OutOfMemoryError: PermGen space 非堆溢出(永久保存区域溢出) 在Run/Debug configuration 的你要运行行的tomcat里面的 vm optio ...
- C#+GDAL读写文件
读取shp文件: private void btnBrower_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFil ...
- word安装楷体gb2312方法。
1:下载:楷体gb2312.http://www.downza.cn/soft/7732.html 2: 双击安装,将会下载楷体2312 的压缩文件,解压得到楷体2312.ttf. 3: 打开控制 ...
- C#让应用程序只运行一个实例的几种方法
一 判断是否有相同的实例已经运行 1 根据“Mutex”判断是否有相同的实例在运行 /// <returns>已有实例运行返回true,否则为false</returns>pu ...
- rest-framework框架的基本组件
快速实例 Quickstart 大致步骤 (1)创建表,数据迁移 (2)创建表序列化类BookSerializer class BookSerializer(serializers.Hyperlink ...