首页 > 其他分享 >371. 牧师约翰最忙碌的一天

371. 牧师约翰最忙碌的一天

时间:2022-12-04 12:46:50浏览次数:63  
标签:约翰 00 int 08 stk low 371 define 牧师

题目链接

371. 牧师约翰最忙碌的一天

牧师约翰在 \(9\) 月 \(1\) 日这天非常的忙碌。

有 \(N\) 对情侣在这天准备结婚,每对情侣都预先计划好了婚礼举办的时间,其中第 \(i\) 对情侣的婚礼从时刻 \(S_i\) 开始,到时刻 \(T_i\) 结束。

婚礼有一个必须的仪式:站在牧师面前聆听上帝的祝福。

这个仪式要么在婚礼开始时举行,要么在结束时举行。

第 \(i\) 对情侣需要 \(D\_i\) 分钟完成这个仪式,即必须选择 \(S_i \sim S_i+D_i\) 或 \(T_i-D_i \sim T_i\) 两个时间段之一。

牧师想知道他能否满足每场婚礼的要求,即给每对情侣安排\(S_i \sim S_i+D_i\) 或 \(T_i-D_i \sim T_i\),使得这些仪式的时间段不重叠。

若能满足,还需要帮牧师求出任意一种具体方案。

注意,约翰不能同时主持两场婚礼,且 所有婚礼的仪式均发生在 \(9\) 月 \(1\) 日当天

如果一场仪式的结束时间与另一场仪式的开始时间相同,则不算重叠。

例如:一场仪式安排在 \(08:00 \sim 09:00\),另一场仪式安排在 \(09:00 \sim 10:00\),则不认为两场仪式出现重叠。

输入格式

第一行包含整数 \(N\)。

接下来 \(N\) 行,每行包含 \(S_i,T_i,D_i\),其中 \(S_i\) 和 \(T_i\) 是 \(hh:mm\) 形式。

输出格式

第一行输出能否满足,能则输出 YES,否则输出 NO

接下来 \(N\) 行,每行给出一个具体时间段安排。

数据范围

\(1 \le N \le 1000\)

输入样例:

2
08:00 09:00 30
08:15 09:00 20

输出样例:

YES
08:00 08:30
08:40 09:00

解题思路

2-SAT

由于 \([s,s+d]\) 和 \([t-d,t]\) 这两个区间只能选择一个,不妨看成一个命题,即令 \(\neg x\) 表示 \([s,s+d]\),\(x\) 表示 \([t-d,t]\),当两个区间重叠时,存在这样两个区间 \([s_i,s_i+d_i],[s_j,s_j+d_j]\) 或者 \([s_i,s_i+d_i],[t_j-d_j,t_j]\) 或者 \([t_i-d_i,t_i],[s_j,s_j+d_j]\) 或者 \([t_i-d_i,t_i],[t_j-d_j,t_j]\),以 \([s_i,s_i+d_i],[s_j,s_j+d_j]\) 这两个区间重叠为例,即不能存在一种逻辑 \(\neg x_i\) 为真并且 \(\neg x_j\)
为真,故当 \(\neg x_i\) 为真时,必然有 \(\neg x_j\) 为假,即有 \(x_i\cup x_j\),则可将该问题转化为 2-SAT 问题

  • 时间复杂度:\((n^2)\)

代码

// Problem: 牧师约翰最忙碌的一天
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/373/
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=2005,M=N*N;
int n;
int h[N],ne[M],e[M],idx;
int dfn[N],low[N],timestamp,scc_cnt,stk[N],top,id[N];
bool in_stk[N];
struct A
{
	int s,t,d;
}a[N/2];
void add(int a,int b)
{
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool over_lap(int a,int b,int c,int d)
{
	return b>c&&d>a;
}
void tarjan(int x)
{
	dfn[x]=low[x]=++timestamp;
	stk[++top]=x,in_stk[x]=true;
	for(int i=h[x];~i;i=ne[i])
	{
		int y=e[i];
		if(!dfn[y])
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(in_stk[y])
			low[x]=min(low[x],dfn[y]);
	}
	if(low[x]==dfn[x])
	{
		int y;
		scc_cnt++;
		do
		{
			y=stk[top--];
			in_stk[y]=false;
			id[y]=scc_cnt;
		}while(y!=x);
	}
}
int main()
{
	memset(h,-1,sizeof h);
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
    	int hhs,mms,hht,mmt,d;
    	scanf("%d:%d %d:%d %d",&hhs,&mms,&hht,&mmt,&d);
    	a[i]={hhs*60+mms,hht*60+mmt,d};
    }
    for(int i=0;i<n;i++)
    	for(int j=i+1;j<n;j++)
    	{
    		if(over_lap(a[i].s,a[i].s+a[i].d,a[j].s,a[j].s+a[j].d))add(i<<1|1,j<<1),add(j<<1|1,i<<1);
    		if(over_lap(a[i].t-a[i].d,a[i].t,a[j].s,a[j].s+a[j].d))add(i<<1,j<<1),add(j<<1|1,i<<1|1);
    		if(over_lap(a[i].s,a[i].s+a[i].d,a[j].t-a[j].d,a[j].t))add(i<<1|1,j<<1|1),add(j<<1,i<<1);
    		if(over_lap(a[i].t-a[i].d,a[i].t,a[j].t-a[j].d,a[j].t))add(i<<1,j<<1|1),add(j<<1,i<<1|1);
    	}
    for(int i=0;i<2*n;i++)
    	if(!dfn[i])tarjan(i);
    for(int i=0;i<n;i++)
    	if(id[i<<1]==id[i<<1|1])
    	{
    		puts("NO");
    		return 0;
    	}
    puts("YES");
    for(int i=0;i<n;i++)
    	if(id[i<<1|1]>id[i<<1])
    		printf("%02d:%02d %02d:%02d\n",(a[i].t-a[i].d)/60,(a[i].t-a[i].d)%60,a[i].t/60,a[i].t%60);
    	else
    		printf("%02d:%02d %02d:%02d\n",a[i].s/60,a[i].s%60,(a[i].s+a[i].d)/60,(a[i].s+a[i].d)%60);
    return 0;
}

标签:约翰,00,int,08,stk,low,371,define,牧师
From: https://www.cnblogs.com/zyyun/p/16949662.html

相关文章

  • 新版H3C华三GB0-191、GB0-371、381、391考试题型及考试介绍
    新版H3C华三GB0-191、GB0-371、381、391考试题型及考试介绍H3CNE (H3CCertifiedNetworkEngineer),即H3C认证网络工程师。考试代码:GB0-191考试时长:60分钟认证方法:上......
  • HDU 3713 Double Maze
    ProblemDescriptionUnlikesinglemaze,doublemazerequiresacommonsequenceofcommandstosolvebothmazes.Seethefigurebelowforaquickunderst......
  • 【XSY4371】star(构造)
    题意:给定值域在\([0,n-1]\)的序列\(a_1,\cdots,a_{m}\),要求构造值域在\([0,n-1]\)的序列\(b_1,\cdots,b_{m}\)和\(c_1,\cdots,c_{m}\),使得\(b_i\)两两不同、\(c......
  • AT2371 [AGC013E] Placing Squares
    AT2371[AGC013E]PlacingSquares设\(f_i\)表示考虑到第\(i\)个点的贡献之和且不考虑坏点。不难发现转移方程为\(f_n=\sum_{i=0}^nf_i\times(n-i)^2\)则当第\(n......
  • 约翰奥利弗通过嫁给卷心菜将 DALL-E 带给大众
    约翰奥利弗通过嫁给卷心菜将DALL-E带给大众人工智能创建的图像似乎终于成为了主流。在约翰·奥利弗的《今晚的最后一周》中,这位喜剧演员/评论员为AI程序献上了一段独......
  • CF371B 题解
    前言题目传送门!更好的阅读体验?这题显然没有蓝的难度。其他题解代码不好看,而且没有讲清楚,那我补一发吧。题目简述有两个数\(a\),\(b\),每次操作可以给\(a\)或\(b\)......