题意:有一个牧师,许多婚礼,每一场他都要出场,开始前c分钟 或结束前c分钟,问有没有方案
思路:这种二选一的,就是套2-SAT。
对于两场婚礼,四种情况 (A开始,B开始),(A结束,B结束),(A开始,B结束),(A结束,B开始)
如果时间冲突的话(max(开始时间) < min(结束时间) ),建边A -> B' 和 B -> A'
思路:这种二选一的,就是套2-SAT。
对于两场婚礼,四种情况 (A开始,B开始),(A结束,B结束),(A开始,B结束),(A结束,B开始)
如果时间冲突的话(max(开始时间) < min(结束时间) ),建边A -> B' 和 B -> A'
用一下强连通SCC,如果A,A'这样一对对应点在同一个分量中,矛盾,没有方案
否则,对于每场婚礼,如果belong[i] < belong[i+n] ,婚礼在开始的时候去
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<list>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<numeric>
#include<functional>
using namespace std;
typedef long long ll;
const int maxn = 2005;
struct edge
{
int to,next;
bool cut;
}ed[maxn*maxn];
int head[maxn], tot;
int Low[maxn], DFN[maxn], Stack[maxn*maxn];
int Index, top;
bool Instack[maxn];
int block,belong[maxn];
int bridge;
int s[maxn],t[maxn],d[maxn];
void init()
{
memset(d,0,sizeof d);
memset(head, -1, sizeof(head));
memset(DFN, 0, sizeof(DFN));
memset(Instack, false, sizeof(Instack));
block = tot = 0;
Index = top = 0;
bridge = 0;
}
void Tarjan(int u,int pre)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u];i != -1;i = ed[i].next)
{
v = ed[i].to;
if( !DFN[v] )
{
Tarjan(v,u);
if( Low[u] > Low[v] )Low[u] = Low[v];
}
else if( Instack[v] && Low[u] > DFN[v] )
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
block++;
do
{
v = Stack[--top];
Instack[v] = false;
belong[v] = block;
}
while( v!=u );
}
}
void add(int x,int y)
{
ed[tot].to = y;
ed[tot].next = head[x];
head[x] = tot++;
}
void SCC(int n)
{
for(int i=1; i<=n; i++)
if(!DFN[i])
Tarjan(i,-1);
}
int main(void)
{
int n;
while(scanf("%d",&n)!=EOF)
{
init();
for(int i = 1; i <= n; i++)
{
int a,b,c;
scanf("%d:%d",&a,&b);
s[i] = a*60+b;
scanf("%d:%d %d",&a,&b,&d[i]);
t[i] = a*60+b;
}
for(int i = 1; i <= n; i++)
{
for(int j = i+1; j <= n; j++)
{
if(max(s[i],s[j]) < min(s[i]+d[i],s[j]+d[j])) //i,j
{
add(i,j+n);
add(j,i+n);
}
if(max(t[i]-d[i],t[j]-d[j]) < min(t[i],t[j])) //i+n,j+n
{
add(i+n,j);
add(j+n,i);
}
if(max(s[i],t[j]-d[j]) < min(s[i]+d[i],t[j]))//i,j+n
{
add(i,j);
add(j+n,i+n);
}
if(max(s[j],t[i]-d[i]) < min(s[j]+d[j],t[i]))//i+n,j
{
add(j,i);
add(i+n,j+n);
}
}
}
SCC(2*n);
int flag = 0;
for(int i = 1; i <= n; i++)
{
if(belong[i] == belong[i+n])
{
flag = 1;
break;
}
}
if(flag)
{
printf("NO\n");
continue;
}
printf("YES\n");
for(int i = 1; i <= n; i++)
{
if(belong[i] < belong[i+n])
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;
}