图论:2-SAT
先象征性地描述一下问题:一组(或者一个)东西有且仅有两种选择,要么选这个,要么选那个,还有一堆的约束条件
图论问题,当然是建边跑图喽
给出模型:
模型一:两者(A,B)不能同时取 那么选择了A就只能选择B’,选择了B就只能选择A’
连边A→B’,B→A’ 模型二:两者(A,B)不能同时不取 那么选择了A’就只能选择B,选择了B’就只能选择A
连边A’→B,B’→A 模型三:两者(A,B)要么都取,要么都不取 那么选择了A,就只能选择B,选择了B就只能选择A,选择了A’就只能选择B’,选择了B’就只能选择A’
连边A→B,B→A,A’→B’,B’→A’ 模型四:两者(A,A’)必取A 那么,那么,该怎么说呢?先说连边吧。
连边A’→A
题目POJ3683
然后说一下这个题的意思:
如果某两个婚礼进行仪式的时间有重合
那么就存在了矛盾关系,通过这些关系连边
Tarjan缩点重新建图(这里建反向图),判断
将一个未着色点 x 上色同时,把与它矛盾的点 y 以及 y 的所有子孙节点上另外一种颜色
上色完成后,进行拓扑排序,选择一种颜色的点输出就是一组可行解
介绍一下实现:
int n,cnt,scc,ind,top;
int a[maxn],b[maxn],belong[maxn],op[maxn];
bool inq[maxn];int dfn[maxn],low[maxn],q[maxn],col[maxn];
int g[maxn],gd[maxn],d[maxn];
struct Edge{int t,next;}e[maxm],ed[maxm];
ind是自增的用来记录dfn,scc是连通分量个数
belong用于存每一个点属于哪一个连通分量
然后op用来记录同一组的互斥条件
col用来存颜色
d用来存点的度数,便于拓扑排序
下面给出完整实现,感觉这个题可以很好地拆成几个很好地模板(就比如说拓扑排序,重新建图,强连通缩点,哈哈)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
const int maxm=;
int n,cnt,scc,ind,top;
int a[maxn],b[maxn],belong[maxn],op[maxn];
bool inq[maxn];int dfn[maxn],low[maxn],q[maxn],col[maxn];
int g[maxn],gd[maxn],d[maxn];
struct Edge{int t,next;}e[maxm],ed[maxm];
void addedge(int u,int v)
{
e[++cnt].t=v;e[cnt].next=g[u];
g[u]=cnt;
}
void addedge2(int u,int v)
{
d[v]++;
ed[++cnt].t=v;ed[cnt].next=gd[u];
gd[u]=cnt;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>'') {if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
//a[2i]-b[2i]前半程
//a[2i-1]-b[2i-1]后半程
bool jud(int x,int y)
{
if(b[x]<=a[y]||a[x]>=b[y]) return ;
return ;
}
void build()
{
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++)
{
if(jud(*i,*j))
{
addedge(*i,*j-);
addedge(*j,*i-);
}
if(jud(*i,*j-))
{
addedge(*i,*j);
addedge(*j-,*i-);
}
if(jud(*i-,*j))
{
addedge(*i-,*j-);
addedge(*j,*i);
}
if(jud(*i-,*j-))
{
addedge(*i-,*j);
addedge(*j-,*i);
}
}
}
void tarjan(int x)
{
//cout<<x<<endl;
dfn[x]=low[x]=++ind;
q[++top]=x;inq[x]=;
for(int tmp=g[x];tmp;tmp=e[tmp].next)
if(!dfn[e[tmp].t])
{
tarjan(e[tmp].t);
low[x]=min(low[e[tmp].t],low[x]);
}
else if(inq[e[tmp].t])
low[x]=min(dfn[e[tmp].t],low[x]);
if(low[x]==dfn[x])
{
int temp=;scc++;
while(temp!=x)
{
temp=q[top--];
inq[temp]=;
belong[temp]=scc;
}
}
}
void rebuild()
{
cnt=;
for(int x=;x<=*n;x++)
for(int tmp=g[x];tmp;tmp=e[tmp].next)
if(belong[x]!=belong[e[tmp].t])
{
//cout<<belong[e[tmp].t]<<" "<<belong[x]<<endl;
addedge2(belong[e[tmp].t],belong[x]);
} }
void dfs(int x)
{
if(col[x]) return;
col[x]=-;
for(int tmp=gd[x];tmp;tmp=ed[tmp].next)
dfs(ed[tmp].t);
}
void topsort()
{
for(int i=;i<=scc;i++)
if(!d[i]) q[++top]=i;
while(top)
{
int temp=q[top--];
//cout<<temp<<endl;
if(col[temp]) continue;
col[temp]=;dfs(op[temp]);
for(int tmp=gd[temp];tmp;tmp=ed[tmp].next)
{
d[ed[tmp].t]--;
if(!d[ed[tmp].t]) q[++top]=ed[tmp].t;
}
}
}
void print(int x)
{
printf("%.2d:",x/);
printf("%.2d ",x%);
}
int main()
{
n=read();
int x;
for(int i=;i<=n;i++)
{
//a[2i]-b[2i]前半程
//a[2i-1]-b[2i-1]后半程
a[*i]=read();
a[*i]=a[*i]*+read();
b[*i-]=read();
b[*i-]=b[*i-]*+read();
x=read();
b[*i]=a[*i]+x;
a[*i-]=b[*i-]-x;
}
build();
for(int i=;i<=*n;i++)
if(!dfn[i]) tarjan(i);
for(int i=;i<=n;i++)
if(belong[*i]==belong[*i-])
{puts("NO");return ;}
puts("YES");
rebuild();
for(int i=;i<=n;i++)
{
op[belong[*i]]=belong[*i-];
op[belong[*i-]]=belong[*i];
}
topsort();
for(int i=;i<=n;i++)
if(col[belong[*i]]==)
print(a[*i]),print(b[*i]),puts("");
else print(a[*i-]),print(b[*i-]),puts("");
return ;
}
图论:2-SAT的更多相关文章
- [leetcode] 题型整理之图论
图论的常见题目有两类,一类是求两点间最短距离,另一类是拓扑排序,两种写起来都很烦. 求最短路径: 127. Word Ladder Given two words (beginWord and end ...
- 多边形碰撞 -- SAT方法
检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形 ...
- 并查集(图论) LA 3644 X-Plosives
题目传送门 题意:训练指南P191 分析:本题特殊,n个物品,n种元素则会爆炸,可以转移到图论里的n个点,连一条边表示u,v元素放在一起,如果不出现环,一定是n点,n-1条边,所以如果两个元素在同一个 ...
- NOIp 2014 #2 联合权值 Label:图论 !!!未AC
题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离. ...
- HDU 5521 [图论][最短路][建图灵感]
/* 思前想后 还是决定坚持写博客吧... 题意: n个点,m个集合.每个集合里边的点是联通的且任意两点之间有一条dis[i]的边(每个集合一个dis[i]) 求同时从第1个点和第n个点出发的两个人相 ...
- SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...
- [转] POJ图论入门
最短路问题此类问题类型不多,变形较少 POJ 2449 Remmarguts' Date(中等)http://acm.pku.edu.cn/JudgeOnline/problem?id=2449题意: ...
- HDU 5934 Bomb 【图论缩点】(2016年中国大学生程序设计竞赛(杭州))
Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- Codeforces 553C Love Triangles(图论)
Solution: 比较好的图论的题. 要做这一题,首先要分析love关系和hate关系中,love关系具有传递性.更关键的一点,hate关系是不能成奇环的. 看到没有奇环很自然想到二分图的特性. 那 ...
- 图论(floyd算法):NOI2007 社交网络
[NOI2007] 社交网络 ★★ 输入文件:network1.in 输出文件:network1.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] 在社交网络( ...
随机推荐
- 基于Ubuntu Server 16.04 LTS版本安装和部署Django之(二):Apache安装和配置
基于Ubuntu Server 16.04 LTS版本安装和部署Django之(一):安装Python3-pip和Django 基于Ubuntu Server 16.04 LTS版本安装和部署Djan ...
- 美年健康股票成交量和K线关系
看下美年健康的股票,这次主要是研究下成交量和K线的关系,以最后5天为例子,股票下跌成交量降低,说明抛压很小,在最后3天,价格突破的时候,成交量是平时的两倍,说明有机构买入, 业绩部分还可以,全民健身是 ...
- CentOS7安装Oracle 11gR2 图文详解
注:Oracle11gR2 X64安装 一.环境准备 安装包: 1.VMware-workstation-full-11.1.0-2496824.exe 2.CentOS-7-x86_64-DVD-1 ...
- Zabbix_agentd 启动报错
C:\zabbix>c:\Zabbix\zabbix_agentd.exe -i -c c:\Zabbix\zabbix_agentd.conf zabbix_agentd.exe [1144] ...
- CCF-NOIP-2018 提高组(复赛) 模拟试题(五)
T1 相遇 [问题描述] 在一场奇怪的梦里,小 Y 来到了一个神奇的国度.这个国度可以用一根数轴表示,小 Y 在 N 处,而小 Y 想吃的美食在 K 处.小 Y 有两种方式移动, 一种叫做步行, 一种 ...
- Visual Studio 2010安装包
点击下载
- N-grams模型、停顿词(stopwords)和标准化处理 - NLP学习(2)
在上一节<Tokenization - NLP(1)>的学习中,我们主要学习了如何将一串字符串分割成单独的字符,并且形成一个词汇集(vocabulary),之后我们将形成的词汇集合转换成计 ...
- HDU 4436 str2int(后缀自动机)(2012 Asia Tianjin Regional Contest)
Problem Description In this problem, you are given several strings that contain only digits from '0' ...
- HDU 4588 Count The Carries(数学统计)
Description One day, Implus gets interested in binary addition and binary carry. He will transfer al ...
- ssh问题_1
昨天配置了虚拟机的ssh,可以相互连接,但是今天早上就不行了,遇到如下错误 [slave1@hadoop ~]$ scp .ssh/id_rsa.pub master@hadoop.master:~/ ...