题意:有N场婚礼,每场婚礼的开始时间为Si,结束时间为Ti,每场婚礼有个仪式,历时Di,这个仪式要么在Si时刻开始,要么在Ti-Di时刻开始,问能否安排每场婚礼举行仪式的时间,使主持人John能参加所有的这些仪式的全过程。

题目链接:http://poj.org/problem?id=3683

——>>每场婚礼的仪式,要么在开始段举行,要么在结束段举行,且一定要举行,要求各场婚礼仪式没冲突——>>2-SAT。。。

2-SAT挺神,针对此类问题,可谓手到擒来。。。

LJ《训练指南》上的写法挺容易理解的。。。于是用上了。。。(相对于2003年伍昱论文中O(n)的算法,在时间上《训练指南》中的写法比不上)。。。

对于2-SAT,建图非常重要。。。

——>>设一场婚礼为i,mark[2*i] == 1表示在其开始段举行仪式,mark[2*i+1] == 1表示在其结束段举行仪式。。。

建图思路:对于一个仪式i和另一个仪式j,若i与j有冲突,则说明i不能举行或者j不能举行。。。即i == 0 || j == 0,所以,i' -> j,j' -> i。。。

#include <cstdio>
#include <cstring>
#include <vector> using namespace std; const int maxn = 1000 + 10; int N;
int S[maxn], S1[maxn], S2[maxn], T[maxn], T1[maxn], T2[maxn], D[maxn];
int t[maxn][2]; struct Twoset {
int n;
vector<int> G[maxn*2];
bool mark[maxn*2];
int stk[maxn*2], c; void init(int n) {
this->n = n;
for(int i = 0; i < 2*n; i++) G[i].clear();
memset(mark, 0, sizeof(mark));
} void add_clause(int x, int xval, int y, int yval) {
x = x * 2 + xval;
y = y * 2 + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
} bool dfs(int x) {
if(mark[x^1]) return false;
if(mark[x]) return true;
mark[x] = true;
stk[++c] = x;
int sz = G[x].size();
for(int i = 0; i < sz; i++) {
int v = G[x][i];
if(!dfs(v)) return false;
}
return true;
} bool YES() {
for(int i = 0; i < 2*n; i += 2) if(!mark[i] && !mark[i+1]) {
c = 0;
if(!dfs(i)) {
while(c) mark[stk[c--]] = false;
if(!dfs(i+1)) return false;
}
}
return true;
} void solve() {
if(YES()) {
puts("YES");
for(int i = 0; i < 2*n; i++) if(mark[i]) {
int id = i / 2;
if(i&1) printf("%02d:%02d %02d:%02d\n", (T[id]-D[id])/60, (T[id]-D[id])%60, T[id]/60, T[id]%60);
else printf("%02d:%02d %02d:%02d\n", S[id]/60, S[id]%60, (S[id]+D[id])/60, (S[id]+D[id])%60);
}
}
else puts("NO");
}
} solver; bool isok(int L1, int R1, int L2, int R2) { //判断两个仪式是否冲突
return R1 <= L2 || R2 <= L1;
} void read() {
for(int i = 0; i < N; i++) {
scanf("%d:%d %d:%d %d", &S1[i], &S2[i], &T1[i], &T2[i], &D[i]);
S[i] = S1[i] * 60 + S2[i];
T[i] = T1[i] * 60 + T2[i];
t[i][0] = S[i];
t[i][1] = T[i] - D[i];
}
} void build() {
for(int i = 0; i < N; i++) for(int a = 0; a < 2; a++)
for(int j = i+1; j < N; j++) for(int b = 0; b < 2; b++)
if(!isok(t[i][a], t[i][a]+D[i], t[j][b], t[j][b]+D[j])) //有冲突,不能同时赋a,b,所以a^1或者b^1成立
solver.add_clause(i, a^1, j, b^1);
} int main()
{
while(scanf("%d", &N) == 1) {
solver.init(N);
read();
build();
solver.solve();
}
return 0;
}

poj - 3683 - Priest John's Busiest Day(2-SAT)的更多相关文章

  1. POJ 3683 Priest John's Busiest Day (2-SAT)

    Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6900   Accept ...

  2. POJ 3683 Priest John's Busiest Day(2-SAT+方案输出)

    Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10010   Accep ...

  3. POJ 3683 Priest John's Busiest Day(2-SAT 并输出解)

    Description John is the only priest in his town. September 1st is the John's busiest day in a year b ...

  4. POJ 3683 Priest John's Busiest Day / OpenJ_Bailian 3788 Priest John's Busiest Day(2-sat问题)

    POJ 3683 Priest John's Busiest Day / OpenJ_Bailian 3788 Priest John's Busiest Day(2-sat问题) Descripti ...

  5. POJ 3683 Priest John's Busiest Day (2-SAT)

    题意:有n对新人要在同一天结婚.结婚时间为Ti到Di,这里有时长为Si的一个仪式需要神父出席.神父可以在Ti-(Ti+Si)这段时间出席也可以在(Di-Si)-Si这段时间.问神父能否出席所有仪式,如 ...

  6. POJ 3683 Priest John's Busiest Day (2-SAT,常规)

    题意: 一些人要在同一天进行婚礼,但是牧师只有1个,每一对夫妻都有一个时间范围[s , e]可供牧师选择,且起码要m分钟才主持完毕,但是要么就在 s 就开始,要么就主持到刚好 e 结束.因为人数太多了 ...

  7. POJ 3683 Priest John's Busiest Day[2-SAT 构造解]

    题意: $n$对$couple$举行仪式,有两个时间段可以选择,问是否可以不冲突举行完,并求方案 两个时间段选择对应一真一假,对于有时间段冲突冲突的两人按照$2-SAT$的规则连边(把不冲突的时间段连 ...

  8. POJ 3683 Priest John's Busiest Day 【2-Sat】

    这是一道裸的2-Sat,只要考虑矛盾条件的判断就好了. 矛盾判断: 对于婚礼现场 x 和 y,x 的第一段可以和 y 的第一段或者第二段矛盾,同理,x 的第二段可以和 y 的第一段或者第二段矛盾,条件 ...

  9. POJ 3683 Priest John's Busiest Day

    看这个题目之前可以先看POJ2186复习一下强联通分量的分解 题意:给出N个开始时间和结束时间和持续时间三元组,持续时间可以在开始后或者结束前,问如何分配可以没有冲突. -----–我是分割线---- ...

随机推荐

  1. Dom对象的方法应用一getElementById技巧、getElementsByName() IE,firefox兼容

    在document对象中有以下三个方法,对于程序员来说,真可谓无人不知,无人不晓,他们分别是: 1.getElementById()                  返回对拥有指定 id 的第一个对 ...

  2. 【英语】Bingo口语笔记(26) - Take系列

    raincheck 改日 take .. off 在这里是请假的意思

  3. IP碎片原理:攻击和防护

    为了加深理解IP协议和一些DoS攻击手段大家有必要看看以下内容,也许对你理解这个概念有所帮助.先来看看IP碎片是如何产生的吧.         一.IP碎片是如何产生的       链路层具有最大传输 ...

  4. HDFS命令行文件操作

    Hadoop文件操作命令形式为 hadoop fs -cmd <args> 说明:cmd是具体的文件操作命令,<args>是一组数目可变的参数. Hadoop最常用的文件操作命 ...

  5. Notify通知

    1.NotificationManager类对象         <1>getSystemService(Context.NOTIFICATION_SERVICE) 获取通知管理对象   ...

  6. vsftpd2.3.2安装、配置详解

    一.vsftpd 简介     Vsftpd是一个基于GPL发布的类UNIX系统的ftp服务器软件.其全称是Very Secure FTP Deamon,在安全性.速度和稳定性都有着不俗的表现.在安全 ...

  7. selenium-grid2 远程并发控制用例执行

    今天闲来无事,随意看了一下selenium,突然注意到grid这个功能以前都是,在读有关selenium的文档时候知道有这么个grid远程控制的功能,但一直没有去试过.所以呢,今天就简单的做了这么个小 ...

  8. 改进duilib的richedit控件的部分功能

    转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41208207 如果要使用透明异形窗体功能,首先要改进duilib库让他本 ...

  9. C++读取二进制文件(某特定格式)

    该格式也不复杂,就是一个二进制文件,格式为:8个通道,每个通道2字节,都为整数,最后两个通道都是0x03FF == 1023d,文件中中若干个8通道. 有个小细节就是:下面代码中 infile.rea ...

  10. iOS学习笔记之Category

    iOS学习笔记之Category 写在前面 Category是类别(也称为类目或范畴),使用Category,程序员可以为任何已有的类添加方法.使用类别可以对框架提供的类(无法获取源码,不能直接修改) ...