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. 一个字符串中可能包含a~z中的多个字符,如有重复,如String data="aavzcadfdsfsdhshgWasdfasdf",求出现次数最多的那个字母及次数,如有多个重复的则都求出。

    主要掌握String中的方法 char[] toCharArray()           将此字符串转换为一个新的字符数组. int indexOf(String str)           返回 ...

  2. java CyclicBarrier 2

    //Listing 6-2. Using a Cyclic Barrier to Decompose a Task into Subtasks import java.util.concurrent. ...

  3. MetaWeblog 同时管理51cto,csdn,sina,163,oschina,cnblogs等博客

    我们技术人一般都会有自己的一个博客,用于记录一些技术笔记,也期望自己的笔记文章可以让更多人知道. 如何让更多人知道自己的博客? 搜索引擎收录,用户通过关键词搜索可能会进入 内容运营,但是一般技术人为了 ...

  4. Delphi XE5 Android 程序退出功能

    Uses FMX.Platform.Android; ... begin {退出程序} MainActivity.finish; end;

  5. Visual Studio 2010扩展让JS与CSS实现折叠

    在Visaul Studio 2010中写js或css代码,缺少像写C#代码时的那种折叠功能,当代码比较多时,就很不方便. 今天发现,已经有VS2010扩展支持这个功能,它就是——JSEnhancem ...

  6. go 安装

    安装golang centos7 直接安装golang yum install golang centos6需添加软件源,然后再安装 rpm -ivh http://ftp.riken.jp/Linu ...

  7. 关于java字符串编译优化问题

    情景一:不好的字符串拼接习惯    起因是这样的:一个大牛在写了一篇关于java字符串优化问题的讲解,他提到:不要使用strObj+otherValue的方法将otherValue转换为字符串形式,因 ...

  8. SQL Server批量数据导出导入BCP使用

    BCP简介 bcp是SQL Server中负责导入导出数据的一个命令行工具,它是基于DB-Library的,并且能以并行的方式高效地导入导出大批量的数据.bcp可以将数据库的表或视图直接导出,也能通过 ...

  9. Vim-Vundle-plugins-scripts

    配置文件.vimrc set tabstop= set softtabstop= set shiftwidth= set noexpandtab set autoindent set cindent ...

  10. block 反向传值回调

    /** *  block 反向传值回调 */ //在第二个控制器中 //   (1)声明block,在基类中已写好 //   (2)写好传值方法 //(1) typedef void (^Return ...