本文共 3419 字,大约阅读时间需要 11 分钟。
在这个问题中,我们需要判断一系列仪式是否存在时间上的冲突。每个仪式可以看作是一个变量,其值可以是0(不举行)或1(举行)。通过将这些变量转化为2-SAT问题,我们可以利用图论中的强连通分量(SCC,Strongly Connected Component)概念来解决冲突问题。
将每个仪式的时间段转化为2-SAT中的变量及其约束条件。具体来说:
通过上述步骤,我们可以将问题转化为一个2-SAT问题,接下来需要使用Tarjan算法来处理这个问题。
Tarjan算法是一种深度优先搜索算法,用于找到图中的强连通分量(SCC)。在2-SAT问题中,强连通分量的划分可以帮助我们判断变量之间的依赖关系。
数据结构准备:
n 和边数 m。head 和 edge 来表示图的邻接表。边的添加:
Tarjan算法执行:
dfn 和低点时间 low。冲突检测:
结果判断:
#include#include #include #include using namespace std;#define INF 0x3f3f3f3f#define full(a, b) memset(a, b, sizeof(a))#define lcm(a, b) (a / gcd(a, b)) * btemplate inline T fpow(T x, T p, T lyd) { T ans = 1; for (; p > 0; p >>= 1, x = (x * x) % lyd) { if (p & 1) { ans = (ans * x) % 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;};stack 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]); 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; }
通过将时间冲突问题转化为2-SAT问题,并利用Tarjan算法进行强连通分量分析,我们可以有效地判断一系列仪式是否存在时间上的冲突。这种方法不仅简化了问题的复杂性,还提供了一个高效的解决方案。
转载地址:http://kbxfk.baihongyu.com/