这题有点难度.
先假设这些婚礼都能办成,若推出矛盾则不能办成.
每个婚礼不是在开始时办就是在结束时办.所以把每个婚礼$i$拆成两个点$i,n+i$分别表示在开始时办和在结束时办.
如果某两个婚礼的时间有交集,那么他们会互相限制.我们可以枚举这两个婚礼,记为$i,j$.
比如说,$i$需要的时间和$j$有重合,那么如果$i$办,$j$就不能办.而$j,j+n$中又必须有一个办,也就是说, 如果$i$办,$j+n$必须办(同理可得其逆否命题如果$j$办,$i+n$必须办).
因此,这些限制关系和这$n+n$个点构成了一个2-SAT模型.
跑一遍tarjan,如果存在矛盾(即$i,i+n$在同一个强连通分量中)则不是所有婚礼都能办成.
接下来考虑如何输出一种方案.
tarjan算法求出的SCC编号满足拓扑序.
因此,直接比较$scc[i],scc[n+i]$即可得到该在$i$办还是该在$n+i$办.
综上,问题在$O(n^2)$的时间内解决.
实现的时候有时间转化等细节需要注意.
/**********/
#define MAXN 2011
#define MAXM 1000011
struct Edge
{
ll v,nxt;
}e[MAXM<<2|1];
ll cnt=0,last[MAXN];
void adde(ll u,ll v)
{
e[++cnt].v=v;
e[cnt].nxt=last[u],last[u]=cnt;
}
ll s[MAXN],t[MAXN],d[MAXN];
bool invaild(ll s1,ll t1,ll s2,ll t2)
{
return t1>s2&&t2>s1;
}
ll dfn[MAXN],low[MAXN],cur=0,scc[MAXN],scnt;
ll stack[MAXN],top=0;
bool ins[MAXN];
void tarjan(ll u)
{
dfn[u]=low[u]=++cur;
stack[++top]=u;ins[u]=1;
for(ll i=last[u];i;i=e[i].nxt)
{
ll v=e[i].v;
if(!dfn[v])
{
tarjan(v);
umin(low[u],low[v]);
}
else if(ins[v])umin(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
++scnt;
while(stack[top]!=u)
{
scc[stack[top]]=scnt;
ins[stack[top]]=0;
--top;
}
scc[stack[top--]]=scnt;
ins[u]=0;
}
}
int main()
{
ll n=read();
for(ll i=1;i<=n;++i)
{
s[i]=read()*60+read();
t[i]=read()*60+read();
d[i]=read();
}
for(ll i=1;i<=n;++i)
for(ll j=1;j<=n;++j)
if(i!=j)
{
if(invaild(s[i],s[i]+d[i],s[j],s[j]+d[j]))adde(i,j+n),adde(j,i+n);
if(invaild(t[i]-d[i],t[i],s[j],s[j]+d[j]))adde(i+n,j+n),adde(j,i);
if(invaild(s[i],s[i]+d[i],t[j]-d[j],t[j]))adde(i,j),adde(j+n,i+n);
if(invaild(t[i]-d[i],t[i],t[j]-d[j],t[j]))adde(i+n,j),adde(j+n,i);
}
for(ll i=1;i<=n+n;++i)
if(!dfn[i])tarjan(i);
for(ll i=1;i<=n;++i)
if(scc[i]==scc[i+n])
{
puts("NO");
return 0;
}
puts("YES");
for(ll i=1;i<=n;++i)
{
ll x=scc[i]>scc[i+n];
if(!x)printf("%02d:%02d %02d:%02d\n",s[i]/60,s[i]%60,(s[i]+d[i])/60,(s[i]+d[i])%60);
else printf("%02d:%02d %02d:%02d\n",(t[i]-d[i])/60,(t[i]-d[i])%60,t[i]/60,t[i]%60);
}
return 0;
}