图论: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 [问题描述] 在社交网络( ...
随机推荐
- 10 TCP 传输控制协议 UDP区别
1.tcp和udp区别 2.TCP通信模型 生活中的电话机 如果想让别人能更够打通咱们的电话获取相应服务的话,需要做一下几件事情: 买个手机 插上手机卡 设计手机为正常接听状态(即能够响铃) 静静的等 ...
- FRDM-KL25Z开发板上电试用
1. 硬件平台:FRDM-KL25Z开发板,先看下板子,Cortex M0+的内核,板子上自带MMA8451Q的三轴加速度传感器,触摸滑动按键,openSDA调试器.MCU主频48MHz,有16KB ...
- vs调试代码的时候断点无法命中
https://blog.csdn.net/xxdddail/article/details/18696399 该链接提供的解决方案主要是如下图片:禁用 图片标记的这个选项即可:
- 实现一个简单版的express
express应该算是早期最优秀的一个node框架了,刚开始学node做后端语言就是用的express,它的cli可以帮我们搭建好项目目录,就像现在的vue,react一样.express本身没有做太 ...
- Selenium页面工厂+数据驱动测试框架
工程的目录结构: pom.xml文件: <?xml version="1.0" encoding="UTF-8"?><project xmln ...
- 容器基础(十): 使用kubernetes部署应用
概述 使用之前的脚本(env/server.py 得到 env/server:v0.1 镜像, env/worker.py 得到 env/worker:v0.1)得到的镜像,在部署好kubernete ...
- hibernate 批量插入
Session session = sessionFactoryUpLowLimit.openSession(); session.beginTransaction(); for(int i=0 ;i ...
- Python之tornado框架实现翻页功能
1.结果如图所示,这里将html页面与网站的请求处理放在不同地方了 start.py代码 import tornado.ioloop import tornado.web from controlle ...
- PhpStorm 配置IDE
IDE => Xdebug => Apache(XAMPP) => Firefox + easist Xdebug 1>XAMPP停止apache服务;2>在安装目录下找 ...
- esayui combotree 只能选择子节点
esayui combotree 只能选择子节点用onBeforeSelect:参数是node,节点被选中之前触发,返回false取消选择动作. 网上找了好多都没一个可用的,要想知道他是子节点还是根节 ...