题目大意:给出开始时间,结束时间和持续时间,每个时间段只能选择[开始时间,开始时间+持续时间]或者[结束时间-持续时间,结束时间],问区间会不会覆盖
解题思路:2-SAT裸题
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int MAXNODE = 2010;
vector<int> G[MAXNODE];
bool mark[MAXNODE];
int n, top;
int Stack[MAXNODE];
int start[MAXNODE], End[MAXNODE], last[MAXNODE];
void init() {
for (int i = 0; i < 2 * n; i++)
G[i].clear();
memset(mark, 0, sizeof(mark));
int h1, m1, h2, m2;
for (int i = 0; i < n; i++) {
scanf("%d:%d%d:%d%d", &h1, &m1, &h2, &m2, &last[i]);
start[i] = h1 * 60 + m1;
End[i] = h2 * 60 + m2;
}
}
bool dfs(int u) {
if (mark[u ^ 1]) return false;
if (mark[u]) return true;
mark[u] = true;
Stack[++top] = u;
for (int i = 0; i < G[u].size(); i++)
if (!dfs(G[u][i])) return false;
return true;
}
bool judge(int s1, int e1, int s2, int e2) {
if (s1 >= s2 && s1 < e2) return true;
if (s2 >= s1 && s2 < e1) return true;
return false;
}
void AddClause(int x, int valx, int y, int valy) {
x = x * 2 + valx;
y = y * 2 + valy;
G[x].push_back(y);
}
bool ok() {
for (int i = 0; i < 2 * n; i += 2) {
if (!mark[i] && !mark[i ^ 1]) {
if (!dfs(i)) {
top = 0;
while (top) mark[Stack[top--]] = false;
if (!dfs(i ^ 1)) return false;
}
}
}
return true;
}
void solve() {
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
for (int x = 0; x < 2; x++)
for (int y = 0; y < 2; y++) {
int s1, e1, s2, e2;
if (x == 0) {
s1 = start[i];
e1 = start[i] + last[i];
}
else {
s1 = End[i] - last[i];
e1 = End[i];
}
if (y == 0) {
s2 = start[j];
e2 = start[j] + last[j];
}
else {
s2 = End[j] - last[j];
e2 = End[j];
}
if (s1 > e1 || s2 > e2) continue;
if (judge(s1, e1, s2, e2)) {
AddClause(i, x, j, y ^ 1);
AddClause(j, y, i, x ^ 1);
}
}
if (!ok()) {
printf("NO\n");
return ;
}
printf("YES\n");
for (int i = 0; i < n; i++) {
int st, ed;
if (mark[i * 2]) {
st = start[i];
ed = start[i] + last[i];
}
else {
st = End[i] - last[i];
ed = End[i];
}
printf("%02d:%02d %02d:%02d\n", st / 60, st % 60, ed / 60, ed % 60);
}
}
int main() {
while (scanf("%d", &n) != EOF) {
init();
solve();
}
return 0;
}