每个婚礼只能选择从开始时间开始或者终点时间结束,所以可以2-sat。
建图:第i个婚礼 从开始时间开始用点 2*i 标记, 在终点时间结束用2*i+1 标记, 比较婚礼 i和j ,如果 2*i 和 2*j 有冲突, 则连一条 2*i到2*j+1的边(其他同理)......
输出解: 先将图缩点,然后建立一个逆向的图,在拓扑输出解。因为如果正向的图,选了一个点,它能到达的点都需要选,而如果逆向的话,我们只需要选择入度为0 的点(这个点可能是缩点前的圈),它只会对它的对立节点(或对立节点所在的圈)有影响,比如 选了2*k 所在的强连通分量,那么2*k+1所在的强连通分量就不能选。我们只需要标记一下颜色就可以了。然后将当前选择节点的出度所对应的点的入度减去,下一个入度为0的点,也是无约束的节点。
#include <cstdio>
#include <iostream>
#include <queue>
#include <string.h>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
#define sfint(x) scanf("%d",&x)
#define sfint2(x,y) scanf("%d%d",&x,&y)
#define sfint3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sfstr(c) scanf("%s",c)
#define sfdl(x) scanf("%lf",&x)
#define sfll(x) scanf("%I64d",&x)
#define sfch(c) scanf("%c",&c)
#define fr(i,s,n) for(int i=s;i<n;++i)
#define cl(a) memset(a,0,sizeof(a))
int n;
const int N = 2010;const int M = 4000010;
struct Edg
{
int u,v,nxt;
}edg[M];
int tote,head[N];
void init(){
tote = 0;
memset(head,-1,sizeof(head));
}
inline void addedg(int u,int v){
edg[tote].u=u;edg[tote].v=v;edg[tote].nxt=head[u];head[u]=tote++;
};
struct WED{
int s,e;
void disp(){
printf("%.2d:%.2d %.2d:%.2d\n",s/60,s%60,e/60,e%60);
}
}wed[2010];
bool against(int i,int j){
if(wed[i].s>=wed[j].e ) return 0;
if(wed[j].s>=wed[i].e) return 0;
return 1;
}
void build(int i ,int j){
if(against(i<<1,j<<1)) addedg(i<<1,j<<1|1);
if(against(i<<1,j<<1|1)) addedg(i<<1,j<<1);
if(against(i<<1|1,j<<1)) addedg(i<<1|1,j<<1|1);
if(against(i<<1|1,j<<1|1)) addedg(i<<1|1,j<<1);
}
int bcnt,stop,dindex;
int DFN[N],low[N],stap[N],belong[N];
bool instack[N];
void tarjan(int u){
DFN[u]=low[u]=++dindex;instack[u]=1;stap[stop++]=u;
for(int i=head[u];i!=-1;i=edg[i].nxt){
int j = edg[i].v;
if (!DFN[j]){
tarjan(j);
if (low[u]>low[j]) low[u]=low[j];
}
else if(instack[j]&&DFN[j]<low[u]) low[u]=DFN[j];
}
if (DFN[u]==low[u]){
++bcnt;
int j;
do{
j=stap[--stop];instack[j]=0;belong[j]=bcnt;
}while(j!=u);
}
}
void tarjan_find(){
cl(DFN);
memset(instack,0,sizeof(instack));
stop = bcnt = dindex=0;
fr(i,0,n*2){
if (!DFN[i])
tarjan(i);
}
}
vector<int> dag[N];
int ind[N];
void makedag(){
int v;
fr(u ,0 ,2*n){
for(int i = head[u];i!=-1;i = edg[i].nxt){
v = edg[i].v;
if (belong[u] != belong[v]){
dag[belong[v]].push_back(belong[u]);
++ind[belong[u]];
}
}
}
}
queue<int> q;
vector<int> ha[N];
int color[N];
void topsort(){
fr(i , 1 , bcnt+1){
if(ind[i]==0){
q.push(i);
}
}
int u,v,siz;
while(!q.empty()){
u = q.front();
q.pop();
siz = dag[u].size();
if(!color[u] ){
color[u] = 1;
for(int i = 0;i< ha[u].size();++i){
color[ha[u][i]]=2;
}
}
fr(i , 0 , siz){
v = dag[u][i];
--ind[v];
if(ind[v] == 0){
q.push(v);
}
}
}
}
void solve(){
fr(i , 0 ,n){
if(belong[2*i] == belong[2*i+1]){
puts("NO");
return ;
}
else {
ha[belong[2 * i]].push_back(belong[2*i+1]);
ha[belong[2 * i + 1]].push_back(belong[2*i]);
}
}
puts("YES");
makedag();
topsort();
fr(i , 0 ,n){
if(color[belong[i<<1]] == 1){
wed[i<<1].disp();
}
else{
wed[i<<1|1].disp();
}
}
}
int main(){
init();
sfint(n);
int x,y,x1,y1,d;
fr(i , 0 ,n){
scanf("%d:%d %d:%d %d",&x,&y,&x1,&y1,&d);
wed[i<<1].s = x*60+y; wed[i<<1].e = wed[i<<1].s + d;
wed[i<<1|1].e = x1*60+y1;wed[i<<1|1].s = wed[i<<1|1].e-d;
}
fr(i , 0 ,n){
fr(j , 0 , n){
if(i!=j)
build(i,j);
}
}
tarjan_find();
solve();
return 0;
}