POJ-3683 Priest John's Busiest Day

图论中的2-SAT。模板题。

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <iostream>
using namespace std;
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define travel(x) for(edge *p=fir[x]; p; p=p->n)
#define travel2(x) for(edge *p=fir2[x]; p; p=p->n)
#define clr(x, c) memset(x, c, sizeof(x))
#define inf 0x7fffffff
#define maxn 2009
#define maxm 4345678
int read()
{
	int x=0; char ch=getchar();
	while (!isdigit(ch)) ch=getchar();
	while (isdigit(ch)) x=x*10+ch-‘0‘, ch=getchar();
	return x;
}
struct edge{int y; edge *n;} e[maxm], *fir[maxn], *fir2[maxn], *pt=e;
int n=read(), s[maxn], t[maxn], d[maxn];
int dfn[maxn], low[maxn], q[maxn], b[maxn], scc, now, top, c[maxn], v[maxn], op[maxn]; bool inq[maxn];

inline void Add(int x, int y){pt->y=y, pt->n=fir[x], fir[x]=pt++;}
inline void Add2(int x, int y){pt->y=y, pt->n=fir2[x], fir2[x]=pt++, v[y]++;}
inline bool can(int a, int b, int c, int d){return(!(b<=c || d<=a));}
void tarjan(int x)
{
	dfn[x]=low[x]=++now;
	q[++top]=x, inq[x]=1;
	travel(x)
		if (!dfn[p->y]) tarjan(p->y), low[x]=min(low[x], low[p->y]);
		else if (inq[p->y]) low[x]=min(low[x], dfn[p->y]);
	if (low[x]==dfn[x])
	{
		scc++; int a=0;
		while (a!=x) a=q[top--], inq[a]=0, b[a]=scc;
	}
}
void dfs(int x)
{
	if (c[x]) return; else c[x]=-1;
	travel2(x) dfs(p->y);
}
int main()
{
	rep(i, 1, n) s[i]=read()*60+read(), t[i]=read()*60+read(), d[i]=read();
	rep(i, 1, n) rep(j, 1, n) if (i!=j)
	{
		if (can(s[i], s[i]+d[i], s[j], s[j]+d[j])) Add(2*i-1, 2*j), Add(2*j-1, 2*i);
		if (can(s[i], s[i]+d[i], t[j]-d[j], t[j])) Add(2*i-1, 2*j-1), Add(2*j, 2*i);
		if (can(t[i]-d[i], t[i], s[j], s[j]+d[j])) Add(2*i, 2*j), Add(2*j-1, 2*i-1);
		if (can(t[i]-d[i], t[i], t[j]-d[j], t[j])) Add(2*i, 2*j-1), Add(2*j, 2*i-1);
	}
	rep(i, 1, 2*n) if (!dfn[i]) tarjan(i);
	rep(i, 1, n) if (b[i*2-1]==b[i*2]) {puts("NO"); return 0;} puts("YES");
	rep(x, 1, 2*n) travel(x) if (b[x]!=b[p->y]) Add2(b[p->y], b[x]);
	rep(i, 1, n) op[b[2*i-1]]=b[2*i], op[b[2*i]]=b[2*i-1];
	rep(i, 1, scc) if(!v[i]) q[++top]=i;
	while(top)
	{
		int now=q[top--];
		if (c[now]) continue;
		c[now]=1; dfs(op[now]);
		travel2(now) if(--v[p->y]==0) q[++top]=p->y;
	}
	rep(i, 1, n)
		if (c[b[i*2-1]]==1) 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;
}

  

POJ-3683 Priest John's Busiest Day

时间: 2024-10-19 19:21:25

POJ-3683 Priest John's Busiest Day的相关文章

POJ 3683 Priest John&#39;s Busiest Day (2-SAT+输出可行解)

题目地址:POJ 3683 第一次做需要输出可行解的题目...大体思路是先用强连通来判断是否有可行解,然后用逆序建图,用拓扑排序来进行染色,然后输出可行解.具体思路见传送门 因为判断的时候少写了一个等号..检查了好长时间..sad... 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #incl

POJ 3683(Priest John&#39;s Busiest Day-强连通分量解决2-SAT)[Template:2-SAT]

Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8144   Accepted: 2769   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 le

POJ 3683.Priest John&#39;s Busiest Day 2-SAT

Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10144   Accepted: 3472   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 l

POJ 3683 Priest John&#39;s Busiest Day(2-SAT)

[题目链接] http://poj.org/problem?id=3683 [题目大意] 每个婚礼有两个时段可以进行特别仪式,特别仪式必须要有神父在场, 神父只有一个,问是否能满足所有婚礼的需求, [题解] 因为两个时段必须要满足一个时段,所以如果一个时段被占用那么另一个时段必须被空出来, 我们根据各个婚礼两个时段之间的冲突关系建边,之后跑2-SAT,判断是否冲突, 若无冲突则输出方案. [代码] #include <cstdio> #include <algorithm> #in

POJ 3683 Priest John&#39;s Busiest Day(2-SAT+方案输出)

Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10010   Accepted: 3425   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 l

POJ 3683 Priest John&#39;s Busiest Day 【2-Sat】

这是一道裸的2-Sat,只要考虑矛盾条件的判断就好了. 矛盾判断: 对于婚礼现场 x 和 y,x 的第一段可以和 y 的第一段或者第二段矛盾,同理,x 的第二段可以和 y 的第一段或者第二段矛盾,条件是 x 的 1或2 段与 y 的 1或2 段有重合,那么选了 x 某一段就不能选择其矛盾的那一段,那就只能选择 y 中的另一段,建立一条 x (u)-> y ( v的对立 ),同理,x (u的对立)<- y ( v ) . 真的,2-sat千万不要用邻接链表!!!卡死卡死卡死!!!稠密图!!!不要

POJ 3684 Priest John&#39;s Busiest Day 2-SAT+输出路径

强连通算法判断是否满足2-sat,然后反向建图,拓扑排序+染色. 一种选择是从 起点开始,另一种是终点-持续时间那个点 开始. 若2个婚礼的某2种时间线段相交,则有矛盾,建边. 容易出错的地方就在于判断线段相交. 若s1<e2&&s2<e1则相交 输出路径的做法可以参考论文2-SAT解法浅析 #include <iostream> #include<cstring> #include<cstdio> #include<string>

HDU2491 Priest John&#39;s Busiest Day

题目链接 题意: 有n个人要进行乒乓球比赛,每个人都一个能力值,每个人出现的次序就是他们住的位置 现在要求进行一场比赛,三个人,裁判的能力值在两个选手之间,住的位置也在两个人的之间 问这种比赛一共可以进行多少次 思路: 用树状数组做,否则TLE,先从左到右扫一遍,计算每点左边大的个数和小的个数, 再从右到左扫一遍,计算每点右边大和小的个数,然后交叉相乘取和就可以了 代码如下: #include<cstdio> #include<cstring> #include<string

UVA - 1420 Priest John&#39;s Busiest Day

题目大意:有一个司仪,要主持 n 场婚礼,给出婚礼的起始时间和终止时间,每个婚礼需要超过一半的时间做为仪式,并且仪式不能终止.问说司仪能否主持 n 场婚礼. 解题思路:贪心,为了尽量主持多的婚礼,每场的仪式时间就一定要尽量短 d = (t - s) / 2 + 1,(因为必须大于一半,所以加 1).然后按照每场婚礼可以最晚结束的时间排序 t - d,(因为要满足所有的婚礼,所以尽量解决早点的仪式,腾出时间来给后面的婚礼),维护一个占用时间值即可. #include <cstdio> #incl