2-SAT

可以把每一次仪式看成变量,0/1的取值分别为开头举行和结尾举行。

转换为2-SAT接受的命题,就是看某一次仪式中有没有重合的时间段,有的话,就按照不冲突的形式连有向边。

然后跑tarjan就行啦,我们把时间全部转成分钟方便处理。。

#include <iostream>
#include <cstdio>
#include <stack>
#include <cstring>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){int X = 0, w = 0; char ch = 0;while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();return w ? -X : X;
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){A ans = 1;for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;return ans;
}
const int N = 5000;
int n, cnt, k, tot, head[N], S[N], T[N], D[N], dfn[N], low[N], scc[N], val[N];
bool ins[N];
struct Edge { int v, next; } edge[N*N];
stack<int> st;void addEdge(int a, int b){edge[cnt].v = b, edge[cnt].next = head[a], head[a] = cnt ++;
}bool overlap(int a, int b, int c, int d){return (a >= c && a < d) || (b > c && b <= d) || (a <= c && b >= d);
}void build(){while(!st.empty()) st.pop();full(head, -1), full(dfn, 0), full(low, 0);full(scc, 0), full(val, 0);cnt = k = tot = 0;
}void tarjan(int s){dfn[s] = low[s] = ++k;ins[s] = true;st.push(s);for(int i = head[s]; i != -1; i = edge[i].next){int u = edge[i].v;if(!dfn[u]){tarjan(u);low[s] = min(low[s], low[u]);}else if(ins[u]) low[s] = min(low[s], dfn[u]);}if(dfn[s] == low[s]){tot ++;int cur;do{cur = st.top(); st.pop();ins[cur] = false;scc[cur] = tot;}while(cur != s);}
}int main(){while(~scanf("%d", &n)){build();int a, b, c, d;for(int i = 1; i <= n; i ++){scanf("%d:%d %d:%d %d", &a, &b, &c, &d, &D[i]);S[i] = a * 60 + b, T[i] = c * 60 + d;}for(int i = 1; i < n; i ++){for(int j = i + 1; j <= n; j ++){if(overlap(S[i], S[i] + D[i], S[j], S[j] + D[j]))addEdge(i, j + n), addEdge(j, i + n);if(overlap(S[i], S[i] + D[i], T[j] - D[j], T[j]))addEdge(i, j), addEdge(j + n, i + n);if(overlap(T[i] - D[i], T[i], S[j], S[j] + D[j]))addEdge(i + n, j + n), addEdge(j, i);if(overlap(T[i] - D[i], T[i], T[j] - D[j], T[j]))addEdge(i + n, j), addEdge(j + n, i);}}for(int i = 1; i <= 2 * n; i ++){if(!dfn[i]) tarjan(i);}bool good = true;for(int i = 1; i <= n; i ++){if(scc[i] == scc[i + n]){good = false;break;}}if(!good) printf("NO\n");else{printf("YES\n");for(int i = 1; i <= n; i ++){val[i] = (scc[i] > scc[i + n]);}for(int i = 1; i <= n; i ++){if(!val[i]) 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;
}

转载于:https://www.cnblogs.com/onionQAQ/p/10845684.html

POJ 3683 Priest John's Busiest Day (算竞进阶习题)相关推荐

  1. [题解]POJ 3683 Priest John's Busiest Day

    [Description] John is the only priest in his town. September 1st is the John's busiest day in a year ...

  2. POJ 3683 Priest John's Busiest Day(2-ST)

    题目链接:http://poj.org/problem?id=3683 题意:有n个婚礼要举行,但是只有一个牧师.第i个婚礼使用牧师的时间长为leni,可以在开始时或结束时使用.问能否使得n个婚礼均举 ...

  3. POJ - 3683 Priest John's Busiest Day(2-SAT+路径打印)

    题目链接:点击查看 题目大意:现在有n对新人要结婚,每一场婚礼都要请牧师主持一个特殊的仪式,这个仪式必须在婚礼的前d分钟或者最后d分钟进行,现在问能否有一种安排,能让牧师参加到每一场婚礼去主持仪式,输 ...

  4. POJ 3683 Priest John's Busiest Day

    2-SAT简单题,判断一下两个开区间是否相交 #include<cstdio> #include<cstring> #include<cmath> #include ...

  5. POJ 2942 Knights of the Round Table (算竞进阶习题)

    很巧的一道点双 两个骑士如果相互憎恨,我们考虑连边的话,不太好处理答案,所以我们尝试一下建反图. 如果两个骑士没有相互憎恨,我们就在他们两个人之间连一条无向边,最后要让你会议召开,那么显然是选择任意一 ...

  6. pku 3683 Priest John's Busiest Day 2-sat判断有误解+输出可行解

    http://poj.org/problem?id=3683 题意: 一个教父,在一天中要给n对新婚夫妇举行婚礼.已知每对夫妇举行婚礼的起始时间Si和终止时间Ti ,教父送祝福的时间要么在Si-> ...

  7. POJ 3974 Palindrome (算竞进阶习题)

    hash + 二分答案 数据范围肯定不能暴力,所以考虑哈希. 把前缀和后缀都哈希过之后,扫描一边字符串,对每个字符串二分枚举回文串长度,注意要分奇数和偶数 #include <iostream& ...

  8. POJ 2245 Addition Chains(算竞进阶习题)

    迭代加深dfs 每次控制序列的长度,依次加深搜索 有几个剪枝: 优化搜索顺序,从大往下枚举i, j这样能够让序列中的数尽快逼近n 对于不同i,j和可能是相等的,在枚举的时候用过的数肯定不会再被填上所以 ...

  9. POJ 3322 Bloxorz(算竞进阶习题)

    bfs 标准广搜题,主要是把每一步可能的坐标都先预处理出来,会好写很多 每个状态对应三个限制条件,x坐标.y坐标.lie=0表示直立在(x,y),lie=1表示横着躺,左半边在(x,y),lie=2表 ...

最新文章

  1. BCH压力测试最终统计
  2. 如何在命令行模式下升级的你Visual Studio的Solution文件
  3. UOJ#449. 【集训队作业2018】喂鸽子 min-max容斥,FFT
  4. idea生成方法注释的正确方法
  5. 华为项目Tree canvas画图2
  6. 3dmaxuv展开很多线_考研 | 最全考研复试时间线!参考价值超大!
  7. 麻省理工18年春软件构造课程阅读11“抽象函数与表示不变量”
  8. MATLAB 计算点到直线的距离
  9. EXCEL对比两列中查找相同的数据
  10. Python利用wakeonlan库 局域网 网络唤醒电脑
  11. JDK源码阅读计划(Day12) BitSet
  12. docker 镜像压缩 docker-squash
  13. 支持度,置信度,提升度的区别和计算
  14. python中的scipy基础知识_python中SciPy是什么?
  15. 求生之路2服务器搭建(基于LinuxGSM一键完成,完美支持8人)
  16. Tk_Batis 介绍和用法以及和Jpa 的区别
  17. 戴森Lightcycle Morph照明灯黑金版上市,中国大陆限量2000台
  18. mysql delete in删除数据
  19. 思否 CEO 高阳受邀出席中国区块链产业高峰论坛
  20. Web3是未来还是大忽悠?

热门文章

  1. 【C++】accumulate函数的用法(STL)
  2. 【汇编】JMP跳转指令的指令长度、直接转移与间接转移、段内跳转与段间跳转
  3. 解决/usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.14' not found问题
  4. Hive jdbc执行seelct 语句时报 return code 1 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
  5. 创建对象、原型、原型链
  6. “聆听”升级,阿里云智能喜迎首席聆听官
  7. APP运营者如何对用户的数据进行分析?
  8. 十一、接口(接口的概念,实现,继承,实现)、抽象类与抽象方法(抽象类,抽象方法概念,使用)...
  9. hdu-acm steps 命运
  10. FLASH与ASP.NET通讯[Flash | CS3 | ActionScript | ASP.NET | FluorineFx ]