先象征性地描述一下问题:一组(或者一个)东西有且仅有两种选择,要么选这个,要么选那个,还有一堆的约束条件

图论问题,当然是建边跑图喽

给出模型:

模型一:两者(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的更多相关文章

  1. [leetcode] 题型整理之图论

    图论的常见题目有两类,一类是求两点间最短距离,另一类是拓扑排序,两种写起来都很烦. 求最短路径: 127. Word Ladder Given two words (beginWord and end ...

  2. 多边形碰撞 -- SAT方法

    检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形 ...

  3. 并查集(图论) LA 3644 X-Plosives

    题目传送门 题意:训练指南P191 分析:本题特殊,n个物品,n种元素则会爆炸,可以转移到图论里的n个点,连一条边表示u,v元素放在一起,如果不出现环,一定是n点,n-1条边,所以如果两个元素在同一个 ...

  4. NOIp 2014 #2 联合权值 Label:图论 !!!未AC

    题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离. ...

  5. HDU 5521 [图论][最短路][建图灵感]

    /* 思前想后 还是决定坚持写博客吧... 题意: n个点,m个集合.每个集合里边的点是联通的且任意两点之间有一条dis[i]的边(每个集合一个dis[i]) 求同时从第1个点和第n个点出发的两个人相 ...

  6. SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

    数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...

  7. [转] POJ图论入门

    最短路问题此类问题类型不多,变形较少 POJ 2449 Remmarguts' Date(中等)http://acm.pku.edu.cn/JudgeOnline/problem?id=2449题意: ...

  8. HDU 5934 Bomb 【图论缩点】(2016年中国大学生程序设计竞赛(杭州))

    Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  9. Codeforces 553C Love Triangles(图论)

    Solution: 比较好的图论的题. 要做这一题,首先要分析love关系和hate关系中,love关系具有传递性.更关键的一点,hate关系是不能成奇环的. 看到没有奇环很自然想到二分图的特性. 那 ...

  10. 图论(floyd算法):NOI2007 社交网络

    [NOI2007] 社交网络 ★★   输入文件:network1.in   输出文件:network1.out   简单对比 时间限制:1 s   内存限制:128 MB [问题描述] 在社交网络( ...

随机推荐

  1. MSSQL如何查看当前数据库的连接数 【转】

    - [SQL Server]版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://ai51av.blogbus.com/logs/52955622.html   如果我们发布 ...

  2. python内置模块[re]

    python内置模块[re] re模块: python的re模块(Regular Expression正则表达式)提供各种正则表达式的匹配操作,在文本解析.复杂字符串分析和信息提取时是一个非常有用的工 ...

  3. iOS URL加解密

    URL加解密 背景介绍 iOS 下URL加解密,项目使用AFNetworking 虽然是使用HTTPS,但是从安全方面考虑,在很多情况下还是需要对url的参数进行加密的. 接口如 https://19 ...

  4. Linux下创建pycharm的快捷方式

    第一步:创建桌面快捷方式文件Pycharm.desktop,并打开 sudo gedit /usr/share/applications/Pycharm.desktop 第二步:在打开的文件Pycha ...

  5. Annoy解析

    Annoy是高维空间求近似最近邻的一个开源库. Annoy构建一棵二叉树,查询时间为O(logn). Annoy通过随机挑选两个点,并使用垂直于这个点的等距离超平面将集合划分为两部分. 如图所示,图中 ...

  6. C#非托管跨线程委托调试

    使用C#调用mingw的so文件,拿视频数据回wpf的界面进行显示,注册了回调函数.C++在调用回调函数时遇到了委托被回收的问题,提示:“类型的已垃圾回收委托进行了回调.这可能会导致应用程序崩溃.损坏 ...

  7. MongoDB Linux下的安装和启动

    1. 下载MongoDB,此处下载的版本是:mongodb-linux-i686-1.8.1.tgz.tar. http://fastdl.mongodb.org/linux/mongodb-linu ...

  8. [比赛总结]ACM div3 G 比赛总结

    这次题目总体感觉和做阅读理解差不多,英文题目读起来相当费劲. 另外,这次比赛整个队伍中我们三个都突出存在的问题就是,把简单问题复杂化,抓不到事物的本质,因此很容易的就被题目误导. 比如C题,明明想到了 ...

  9. springmvc项目搭建五-postgresql+easyui的数据显示

    上一篇虽然完成了页面的显示,但是是假数据,本篇添加了postgresql的数据库,将登陆的校验和数据的显示都通过数据库来完成. 我是在本地搭建了一个postgre的数据库,就先新建两张表吧,一个用于用 ...

  10. pta编程(1-8)

    知识点:本次编程运用到的格式 #include<stdio.h> int main(void) { printf(); return 0; } 过程:1-3.没什么问题,就是注意字符的输入 ...