大意略。
关键在于怎样去建图,有冲突之间的点指点连边,然后通过染色的方法去找可行的一组解。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdlib> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <map> using namespace std; const int maxn = 2010; const int maxm = 1010*1010*9; struct Edge { int v, w; int next; }edge[maxm], edge2[maxm]; int first2[maxn]; int cnt2; int first[maxn], stack[maxn], ins[maxn], dfn[maxn], low[maxn]; int belong[maxn]; int n, m, k; int cnt; int scnt, top, tot; void init() { cnt = 0; cnt2 = 0; scnt = top = tot = 0; memset(first, -1, sizeof(first)); memset(first2, -1, sizeof(first2)); memset(dfn, 0, sizeof(dfn)); memset(ins, 0, sizeof(ins)); memset(low, 0, sizeof(low)); } void read_graph(int u, int v) { edge[cnt].v = v; edge[cnt].next = first[u], first[u] = cnt++; } void read_graph2(int u, int v) { edge2[cnt2].v = v; edge2[cnt2].next = first2[u], first2[u] = cnt2++; } void dfs(int u) { int v; low[u] = dfn[u] = ++tot; stack[top++] = u; ins[u] = 1; for(int e = first[u]; e != -1; e = edge[e].next) { v = edge[e].v; if(!dfn[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if(ins[v]) { low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]) { scnt++; do { v = stack[--top]; belong[v] = scnt; ins[v] = 0; } while(u != v); } } void readint(int &x) { char c; while(!isdigit(c)) c = getchar(); x = 0; while(isdigit(c)) { x = x*10 + c-'0'; c = getchar(); } } void writeint(int x) { if(x > 9) writeint(x/10); putchar(x%10+'0'); } void Tarjan() { for(int v = 1; v <= 2*n; v++) if(!dfn[v]) dfs(v); } int judge(int start1, int last1, int start2, int last2) { if(start2 < start1+last1 && start1 < start2+last2) return 1; return 0; } int sta[maxn], end[maxn], la[maxn]; void read_case() { init(); for(int i = 1; i <= n; i++) { int h1, m1, h2, m2, last; scanf("%d:%d %d:%d %d", &h1, &m1, &h2, &m2, &last); sta[i] = h1*60+m1, end[i] = h2*60+m2, la[i] = last; } for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(i != j) { if(judge(sta[i], la[i], sta[j], la[j])) read_graph(i, j+n); if(judge(sta[i], la[i], end[j]-la[j], la[j])) read_graph(i, j); if(judge(end[i]-la[i], la[i], sta[j], la[j])) read_graph(i+n, j+n); if(judge(end[i]-la[i], la[i], end[j]-la[j], la[j])) read_graph(i+n, j); } } int hash[maxn]; int color[maxn]; int ind[maxn]; void toposort() { queue<int> Q; for(int i = 1; i <= scnt; i++) if(!ind[i]) Q.push(i); while(!Q.empty()) { int u = Q.front(); Q.pop(); if(!color[u]) color[u] = 1, color[hash[u]] = 2; for(int e = first2[u]; e != -1; e = edge2[e].next) { int v = edge2[e].v; if(--ind[v] == 0) Q.push(v); } } } void build() { memset(color, 0, sizeof(color)); memset(ind, 0, sizeof(ind)); for(int u = 1; u <= 2*n; u++) { for(int e = first[u]; e != -1; e = edge[e].next) { int v = edge[e].v; if(belong[u] != belong[v]) read_graph2(belong[v], belong[u]), ind[belong[u]]++; } } } int check() { for(int i = 1; i <= n; i++) { if(belong[i] == belong[i+n]) return 0; else hash[belong[i]] = belong[i+n], hash[belong[i+n]] = belong[i]; } return 1; } void output() { printf("YES "); int h1, m1, h2, m2; for(int i = 1; i <= n; i++) { if(color[belong[i]] == 1) { h1 = sta[i]/60; m1 = sta[i]%60; h2 = (sta[i]+la[i])/60; m2 = (sta[i]+la[i])%60; printf("%02d:%02d %02d:%02d ", h1, m1, h2, m2); } else { h1 = (end[i]-la[i])/60; m1 = (end[i]-la[i])%60; h2 = end[i]/60; m2 = end[i]%60; printf("%02d:%02d %02d:%02d ", h1, m1, h2, m2); } } } void solve() { read_case(); Tarjan(); if(check()) { build(); toposort(); output(); } else printf("NO "); } int main() { while(~scanf("%d", &n)) { solve(); } return 0; }