Priest John's Busiest Day
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 8170   Accepted: 2784   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
方法一:tarjan缩点+拓扑排序
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
#include"algorithm"
#include"string.h"
#include"string"
#include"vector"
#include"stack"
#include"map"
#define inf 0x3f3f3f3f
#define M 2009
using namespace std;
struct node
{
int u,v,next;
}edge[M*M*5];
stack<int>q;
struct EDGE
{
int v;
EDGE(int vv)
{
v=vv;
}
};
vector<EDGE>Edge[M];
int t,head[M],low[M],dfn[M],belong[M],num,index,use[M],n,degree[M],Color[M],fp[M];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void tarjan(int u)
{
low[u]=dfn[u]=++index;
q.push(u);
use[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(use[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
num++;
int vv;
do
{
vv=q.top();
q.pop();
use[vv]=0;
belong[vv]=num;
}while(vv!=u);
}
}
int psq(int n)
{
int i;
num=index=0;
memset(use,0,sizeof(use));
memset(dfn,0,sizeof(dfn));
for(i=1;i<=2*n;i++)
if(!dfn[i])
tarjan(i);
for(i=1;i<=n;i++)
if(belong[i]==belong[i+n])
return 0;
return 1;
}
struct Time
{
int l,r;
}time[M];
int ok(Time a,Time b)
{
if(a.r<=b.l||b.r<=a.l)
return 0;
return 1;
}
int op(int u)
{
if(u<=n)
return n+u;
else
return u-n;
}
int main()
{
int i,j;
while(scanf("%d",&n)!=-1)
{
for(i=1;i<=n;i++)
{
int h1,h2,m1,m2,d;
scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&d);
time[i].l=h1*60+m1;
time[i].r=h1*60+m1+d;
time[i+n].l=h2*60+m2-d;
time[i+n].r=h2*60+m2;
}
init();
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(ok(time[i],time[j]))
{
add(i,j+n);
add(j,i+n);
}
if(ok(time[i],time[j+n]))
{
add(i,j);
add(j+n,i+n);
}
if(ok(time[i+n],time[j]))
{
add(i+n,j+n);
add(j,i);
}
if(ok(time[i+n],time[j+n]))
{
add(i+n,j);
add(j+n,i);
}
}
}
if(psq(n))//拓扑排序输出可行解
{
printf("YES\n");
memset(degree,0,sizeof(degree));//缩点的入度
memset(Color,0,sizeof(Color));//染色
for(i=0;i<t;i++)
{
int u=edge[i].u;
int v=edge[i].v;
fp[belong[u]]=belong[op(u)];//记录当前点所在的联通块与对应点所在联通块的相互影射
fp[belong[op(u)]]=belong[u];
if(belong[u]!=belong[v])
{
Edge[belong[v]].push_back(EDGE(belong[u]));//缩点建图,若不在同一个连通块则建立反边
degree[belong[u]]++;
}
}
queue<int>q;
for(i=1;i<=num;i++)
if(degree[i]==0)q.push(i);//入度为0的点入队
while(!q.empty())
{
int u=q.front();
q.pop();
if(Color[u]==0)//对未着色的点着色同时把对立点所在连通块着为相反的颜色
{
Color[u]=1;
Color[fp[u]]=-1;
}
for(i=0;i<(int)Edge[u].size();i++)
{
int v=Edge[u][i].v;
if(--degree[v]==0)
q.push(v);
}
}
for(i=1;i<=n;i++)
{
if(Color[belong[i]]==1)//连通块标记为1的是可行解
printf("%02d:%02d %02d:%02d\n",time[i].l/60,time[i].l%60,time[i].r/60,time[i].r%60);
else
printf("%02d:%02d %02d:%02d\n",time[i+n].l/60,time[i+n].l%60,time[i+n].r/60,time[i+n].r%60);
}
for(i=1;i<=num;i++)
Edge[i].clear();
}
else
printf("NO\n");
}
}

方法二:dfs+枚举(字典序最小)

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
#include"algorithm"
#include"string.h"
#include"string"
#include"vector"
#include"stack"
#include"map"
#define inf 0x3f3f3f3f
#define M 2009
using namespace std;
struct node
{
int u,v,next;
}edge[M*M*5];
stack<int>q;
struct EDGE
{
int v;
EDGE(int vv)
{
v=vv;
}
};
vector<EDGE>Edge[M];
int t,head[M],low[M],dfn[M],belong[M],num,index,use[M],color[M],s[M],cnt,n,degree[M],Color[M],fp[M];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
struct Time
{
int l,r;
}time[M];
int ok(Time a,Time b)
{
if(a.r<=b.l||b.r<=a.l)
return 0;
return 1;
}
int op(int u)
{
if(u<=n)
return n+u;
else
return u-n;
}
int dfs(int u)
{
if(color[u]==1)
return 1;
if(color[u]==-1)
return 0;
s[cnt++]=u;
color[u]=1;
color[op(u)]=-1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!dfs(v))
return 0;
}
return 1;
}
int slove(int n)
{
int i,j;
memset(color,0,sizeof(color));
for(i=1;i<=2*n;i++)
{
if(color[i])continue;
cnt=0;
if(!dfs(i))
{
for(j=0;j<cnt;j++)
color[s[j]]=color[op(s[j])]=0;
if(!dfs(op(i)))
return 0;
}
}
return 1;
}
int main()
{
int i,j;
while(scanf("%d",&n)!=-1)
{
for(i=1;i<=n;i++)
{
int h1,h2,m1,m2,d;
scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&d);
time[i].l=h1*60+m1;
time[i].r=h1*60+m1+d;
time[i+n].l=h2*60+m2-d;
time[i+n].r=h2*60+m2;
}
init();
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(ok(time[i],time[j]))
{
add(i,j+n);
add(j,i+n);
}
if(ok(time[i],time[j+n]))
{
add(i,j);
add(j+n,i+n);
}
if(ok(time[i+n],time[j]))
{
add(i+n,j+n);
add(j,i);
}
if(ok(time[i+n],time[j+n]))
{
add(i+n,j);
add(j+n,i);
}
}
}
if(slove(n))
{
printf("YES\n");
for(i=1;i<=n;i++)
{
if(color[i]==1)
printf("%02d:%02d %02d:%02d\n",time[i].l/60,time[i].l%60,time[i].r/60,time[i].r%60);
if(color[i+n]==1)
printf("%02d:%02d %02d:%02d\n",time[i+n].l/60,time[i+n].l%60,time[i+n].r/60,time[i+n].r%60);
}
for(i=1;i<=num;i++)
Edge[i].clear();
} else
printf("NO\n");
}
}

2-sat 输出任意一组可行解&拓扑排序+缩点 poj3683的更多相关文章

  1. poj 3683 2-sat问题,输出任意一组可行解

    /* 2sat问题 输出任意一组可行解 */ #include<stdio.h> #include<string.h> #include<stdlib.h> #in ...

  2. HDU 1507 Uncle Tom's Inherited Land*(二分匹配,输出任意一组解)

    Uncle Tom's Inherited Land* Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  3. poj 3648 2-sat 输出任意一组解模板

    转载地址:http://blog.csdn.net/qq172108805/article/details/7603351 /* 2-sat问题,题意:有对情侣结婚,请来n-1对夫妇,算上他们自己共n ...

  4. 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)

    https://www.luogu.org/problemnew/show/P4174 最大权闭合子图的模板 每个通讯站建一个点,点权为-Pi:每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连 ...

  5. CF 274D Lovely Matrix 拓扑排序,缩点 难度:2

    http://codeforces.com/problemset/problem/274/D 这道题解题思路: 对每一行统计,以小值列作为弧尾,大值列作为弧头,(-1除外,不连弧),对得到的图做拓扑排 ...

  6. BZOJ3832[Poi2014]Rally——权值线段树+拓扑排序

    题目描述 An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long di ...

  7. UVA 10305 Ordering Tasks(拓扑排序的队列解法)

    题目链接: https://vjudge.net/problem/UVA-10305#author=goodlife2017 题目描述 John有n个任务,但是有些任务需要在做完另外一些任务后才能做. ...

  8. BFS (1)算法模板 看是否需要分层 (2)拓扑排序——检测编译时的循环依赖 制定有依赖关系的任务的执行顺序 djkstra无非是将bfs模板中的deque修改为heapq

    BFS模板,记住这5个: (1)针对树的BFS 1.1 无需分层遍历 from collections import deque def levelOrderTree(root): if not ro ...

  9. Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) E. Tree Folding 拓扑排序

    E. Tree Folding 题目连接: http://codeforces.com/contest/765/problem/E Description Vanya wants to minimiz ...

随机推荐

  1. Lazarus解决无法识别中文路径的方法

    procedure TForm1.Button1Click(Sender: TObject); var FileN:string; begin if self.OpenDialog1.Execute ...

  2. Python中Unicode字符串

    Python中Unicode字符串 字符串还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节(byte ...

  3. 非模态对话框的PreTranslateMessage() 没有用,无法进去

    非模态对话框的的PreTranslateMessage确实进不去, 自然也无法用重载PreTranslateMessage的方法来响应键盘消息. 可以用Hook的方法来使其生效. http://bbs ...

  4. (转)web网站架构演变

    浅谈web网站架构演变过程   前言 我们以javaweb为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变.   该系统具备的功能:   用户模块:用户注册和管理 商品模块:商品展示和管 ...

  5. 那些证书相关的玩意儿(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12等)[zz]

    openssl dgst –sign privatekey.pem –sha1 –keyform PEM –c c:\server.pem 将文件用sha1摘要,并用privatekey.pem中的私 ...

  6. PM2的使用

    PM2 是一个带有负载均衡功能的 Node 应用的进程管理器. 安装 npm install -g pm2 启动程序:pm2 start <app_name|id|all> 列举进程:pm ...

  7. ArcGIS Engine开发之旅10--空间参考及坐标转换

    原文:ArcGIS Engine开发之旅10--空间参考及坐标转换 空间参考(Spatial Reference)是 GIS 数据的骨骼框架,能够将我们的数据定位到相应的位置,为地图中的每一点提供准确 ...

  8. [LeetCode]题解(python):062 Unique path

    题目来源 https://leetcode.com/problems/unique-paths/ A robot is located at the top-left corner of a m x  ...

  9. Subway---poj2502(最短路)

    题目链接:http://poj.org/problem?id=2502 人走路的速度是10km/h,地铁的速度是40km/h题目给出一个起点,一个终点,以及几条地铁线路运行的站点.题目给的点的做坐标单 ...

  10. Selenium2学习-009-WebUI自动化实战实例-007-Selenium 8种元素定位实战实例源代码(百度首页搜索录入框及登录链接)

    此 文主要讲述用 Java 编写 Selenium 自动化测试脚本编写过程中,通过 ID.name.xpath.cssSelector.linkText.className.partialLinkTe ...