Priest John's Busiest Day
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 6900   Accepted: 2363   Special Judge

Description

John is the only priest in his town. September 1st is the John's busiest day in a year because there is an old legend in the town that the couple who get married on that day will be forever blessed by the God of Love. This year N couples plan to get married on the blessed day. The i-th couple plan to hold their wedding from time Si to time Ti. According to the traditions in the town, there must be a special ceremony on which the couple stand before the priest and accept blessings. The i-th couple need Di minutes to finish this ceremony. Moreover, this ceremony must be either at the beginning or the ending of the wedding (i.e. it must be either from Si to Si + Di, or from Ti - Di to Ti). Could you tell John how to arrange his schedule so that he can present at every special ceremonies of the weddings.

Note that John can not be present at two weddings simultaneously.

Input

The first line contains a integer N ( 1 ≤ N ≤ 1000). 
The next N lines contain the SiTi and DiSi and Ti are in the format of hh:mm.

Output

The first line of output contains "YES" or "NO" indicating whether John can be present at every special ceremony. If it is "YES", output another N lines describing the staring time and finishing time of all the ceremonies.

Sample Input

2
08:00 09:00 30
08:15 09:00 20

Sample Output

YES
08:00 08:30
08:40 09:00

Source

题意:一个小镇里面只有一个牧师,现在有些新人要结婚,需要牧师分别去主持一个仪式,给出每对新人婚礼的开始时间 s 和结束时间 t ,还有他们俩的这个仪式需要的时间(每对新人需要的时间长短可能不同) d ,牧师可以在婚礼开始的时间 d 内(s 到 s+d)或者是结束前的时间 d 内(t - d 到 t)完成这个仪式。现在问能否给出一种安排,让牧师能完成所有夫妇婚礼的仪式,如果可以,输出一种安排。

我们把每个婚礼可能的两个时间段看做两个点 A 和 A’,显然,如果两个时间段冲突(比如 A 和 B 的时间重合),那么需要建边(A -> B' ),(B -> A‘),判断出是否存在解后,需要输出一组解,这里的方法是 赵爽 的《2-SAT 解法浅析》里面看的,有详细的证明。

具体操作就是:求强联通,缩点重新建图(这里建反向图,参见论文),然后给图中的点着色,将一个未着色点 x 上色同时,把与它矛盾的点 y 以及 y 的所有子孙节点上另外一种颜色,上色完成后,进行拓扑排序,选择一种颜色的点输出就是一组可行解。

#include<iostream>
#include<cstdio>
#include<cstring> using namespace std; const int VM=;
const int EM=; struct Point{
int st,et;
}p[VM]; struct Edge{
int frm,to,nxt;
}edge1[EM<<],edge2[EM<<]; int n,m,tot,cnt1,cnt2,dep,top,atype,head1[VM],head2[VM];
int dfn[VM],low[VM],vis[VM],belong[VM],indeg[VM];
int stack[VM],ans[VM],mark[VM],color[VM],que[VM]; //color[]为是否选择标志 //1表示选择,0表示不选择 void Init(){
cnt1=, cnt2=, atype=, dep=, top=, tot=;
memset(head1,-,sizeof(head1));
memset(head2,-,sizeof(head2));
memset(vis,,sizeof(vis));
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(belong,,sizeof(belong));
memset(indeg,,sizeof(indeg));
memset(ans,,sizeof(ans));
memset(mark,,sizeof(mark));
memset(color,,sizeof(color));
} void addedge1(int cu,int cv){ //原图增加一条边
edge1[cnt1].frm=cu; edge1[cnt1].to=cv; edge1[cnt1].nxt=head1[cu];
head1[cu]=cnt1++;
} void addedge2(int cu,int cv){ //缩点图增加一条边
edge2[cnt2].frm=cu; edge2[cnt2].to=cv; edge2[cnt2].nxt=head2[cu];
head2[cu]=cnt2++;
} int judge(int a,int b){
if( p[a].et <= p[b].st || p[b].et <= p[a].st )return ;
return ;
} void Tarjan(int u){ //Tarjan算法求强连通分量
dfn[u]=low[u]=++dep;
stack[top++]=u;
vis[u]=;
for(int i=head1[u];i!=-;i=edge1[i].nxt){
int v=edge1[i].to;
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(vis[v])
low[u]=min(low[u],dfn[v]);
}
int j;
if(dfn[u]==low[u]){
atype++;
do{
j=stack[--top];
belong[j]=atype;
vis[j]=;
}while(u!=j);
}
} void solve(){
for(int i=;i<n;i++) //n表示点的个数
if(!dfn[i])
Tarjan(i);
int flag=;
for(int i=;i<m;i++){ //共 m 场婚礼,注意这里的m=n/2
if(belong[*i]==belong[*i+]){
flag=;
break;
}
//这里,为着色做准备,mark[x]保存的是和编号为 x 的连通分量矛盾的连通分量的编号
//在赵爽的论文中有证明,这样可以保证拓扑求解的可行性
//b 和 b' 所在的连通分量是矛盾的(如果不矛盾,那么2-SAT无解)
mark[ belong[*i] ]=belong[*i+];
mark[ belong[*i+] ]=belong[*i];
}
if(flag==){
printf("NO\n");
return ;
}
printf("YES\n");
for(int i=;i<cnt1;i++)
if(belong[edge1[i].frm]!=belong[edge1[i].to]){
addedge2(belong[edge1[i].to],belong[edge1[i].frm]);
indeg[belong[edge1[i].frm]]++;
} int head=,tail=; //拓扑排序求解
for(int i=;i<=atype;i++)
if(indeg[i]==) //入度为0入队列
que[tail++]=i;
while(head<tail){
int u=que[head++];
if(color[u]==){ //对于未着色的点x,将x染成红色1,同时将与x矛盾的点cf[x]染成蓝色-1。
color[u]=;
color[mark[u]]=-;
}
for(int i=head2[u];i!=-;i=edge2[i].nxt){
int v=edge2[i].to;
if(--indeg[v]==) //入度为0
que[tail++]=v; //入队列
}
} int a,b,c,d;
for(int i=;i<m;i++){
if(color[ belong[*i] ]==){//如果颜色和所选颜色相同,输出点 b
a=p[*i].st/;
b=p[*i].st%;
c=p[*i].et/;
d=p[*i].et%;
printf("%02d:%02d %02d:%02d\n",a,b,c,d);
}
else{//否则输出点 b'
a=p[*i+].st/;
b=p[*i+].st%;
c=p[*i+].et/;
d=p[*i+].et%;
printf("%02d:%02d %02d:%02d\n",a,b,c,d);
}
}
} int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d",&m)){
Init();
int a,b,c,d,t;
for(int i=;i<m;i++){
scanf("%d:%d %d:%d %d",&a,&b,&c,&d,&t);
int t1=*a+b, t2=*c+d;
p[tot].st=t1, p[tot++].et=t1+t;
p[tot].st=t2-t, p[tot++].et=t2;
}
for(int i=;i<m;i++)
for(int j=;j<m;j++)
if(i!=j){
if(judge(*i,*j)==) addedge1(*i,*j+);
if(judge(*i,*j+)==) addedge1(*i,*j); if(judge(*i+,*j)==) addedge1(*i+,*j+);
if(judge(*i+,*j+)==) addedge1(*i+,*j);
}
n=tot; //n表示点的个数
solve();
}
return ;
}

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: 10010   Accep ...

  2. 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 ...

  3. poj - 3683 - Priest John's Busiest Day(2-SAT)

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

  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. 关于Linux路由表的route命令

    转自:http://www.cnblogs.com/gunl/archive/2010/09/14/1826234.html 查看 Linux 内核路由表 使用下面的 route 命令可以查看 Lin ...

  2. ExtJS学习笔记2:响应事件、使用AJAX载入数据

    响应事件: 1.设置一个html标记 <div id="my-div">Ext JS 4 Cookbook</div> 2.使用get函数获取此标记对象 v ...

  3. Office办公 如何设置WPS的默认背景大小

    设计-页面设置,然后修改宽度和高度   因为我们只是需要背景跟平面差不多大(不同屏幕比如宽屏的就比较长),修改宽度和高度的时候注意文字之类的也会被拉伸缩放,所以自己改了之后看效果,比如我100,50的 ...

  4. iOS 两个应用之间的切换

    A 跳到B NSURL *urlT = [NSURL URLWithString:@"TestB://XXXXXXX"]; //注意“://”后面可以任意传参数.这些参数传过去后当 ...

  5. Windows 10 中的 Shell 指令

    这篇文章本无技术含量,也不高大上,不过想想,还是写下来吧,肯定有人会用得到的. 常玩系统的朋友,应该知道 Shell 指令,这是一个很好玩很神奇的指令.利用它,可以用简短的单词,轻易地打开系统中的一些 ...

  6. 【树莓派】服务配置相关2:基于RPi Desktop的服务配置

    该文接续之前写过的一篇:[树莓派]服务配置相关. 这是我个人用来进行树莓派盒子安装配置的脚本,对于外部其他博友,可以部分参考,但不需要逐个引用. 现在有一定更新,部分按如下脚本来操作: step1: ...

  7. .NET MVC中登陆授权过滤器的使用

    1.写个类LoginAuthorityAttribute,继承自AuthorizeAttribute using System; using System.Collections.Generic; u ...

  8. SQL中Union和UnionAll的使用

    SQL中Union和UnionAll的使用 1.建立一个Student表 ,如下: 2.建立一个Teacher表,如下: 3.使用Union,将去重并组合表,效果: 4.使用Union All,不去重 ...

  9. FILTER——JAVA

    一.概念 Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或 ...

  10. SQL Server配置支持中文