题目大意:给出开始时间,结束时间和持续时间,每个时间段只能选择[开始时间,开始时间+持续时间]或者[结束时间-持续时间,结束时间],问区间会不会覆盖

解题思路: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;
}