pku 3683 Priest John's Busiest Day 2-sat判断有误解+输出可行解
http://poj.org/problem?id=3683
题意:
一个教父,在一天中要给n对新婚夫妇举行婚礼。已知每对夫妇举行婚礼的起始时间Si和终止时间Ti ,教父送祝福的时间要么在Si->Si +Di 要么在Ti - Di->Ti。问在这一天中,教父如何安排才能对着n对新人都送去祝福?
思路:
把每对新人的婚礼的起始时间和结束时间加减Di后分成两个对立的点,然后检查每个点(这里每个点表示一个时间段,教父在这一事件段里送上祝福)是否存在区间相交,如果i与j存在相交则
i->j^1建边。然后将缩点后的图重新反向建图,利用拓扑排序,输出解。
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll long long #define inf 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define N 2007 #define M 1000007 using namespace std; struct node { int v,u; int next; }g[N*N],rg[N*N]; int head[N],ct; int H[N],ht; int dfn[N],low[N]; int belong[N],stk[N]; bool isn[N]; int col[N],ind[N],opp[N]; int idx,cnt,top; struct time { int s,e; }tm[N]; int n; void add(int u,int v) { g[ct].u = u; g[ct].v = v; g[ct].next = head[u]; head[u] = ct++; } void build() { int i,j; CL(head,-1); ct = 0; for (i = 0; i < 2*n; ++i) { low[i] = dfn[i] = -1; belong[i] = 0; col[i] = 0; ind[i] = 0; isn[i] = false; opp[i] = 0; for (j = 0; j < 2*n; ++j) { if (i == j || (i^1) == j) continue; if (tm[i].s < tm[j].e && tm[i].e > tm[j].s) { add(i,j^1); } } } idx = top = cnt = 0; } void radd(int u,int v) { rg[ht].v = v; rg[ht].next = H[u]; H[u] = ht++; } void rbuild() { CL(H,-1); ht = 0; for (int i = 0; i < ct; ++i) { if (belong[g[i].u] != belong[g[i].v]) { radd(belong[g[i].v],belong[g[i].u]); ind[belong[g[i].u]]++; } } } void topsort() { int i; queue<int>q; for (i = 1; i <= cnt; ++i) { if (ind[i] == 0) q.push(i); } while (!q.empty()) { int u = q.front(); q.pop(); if (col[u] == 0) { col[u] = 1; col[opp[u]] = -1; } for (i = H[u]; i != -1; i = rg[i].next) { int v = rg[i].v; ind[v]--; if (ind[v] == 0) q.push(v); } } } void tarjan(int u) { int i,j; dfn[u] = low[u] = ++idx; isn[u] = true; stk[++top] = u; for (i = head[u]; i != -1; i = g[i].next) { int v = g[i].v; if (dfn[v] == -1) { tarjan(v); low[u] = min(low[u],low[v]); } else if (isn[v]) { low[u] = min(low[u],dfn[v]); } } if (dfn[u] == low[u]) { cnt++; do { j = stk[top--]; isn[j] = false; belong[j] = cnt; } while (j != u); } } void solve() { int i; for (i = 0; i < 2*n; ++i) { if (dfn[i] == -1) tarjan(i); } bool flag = false; for (i = 0; i < n; ++i) { if (belong[2*i] == belong[2*i + 1]) { flag = true; break; } opp[belong[2*i]] = belong[2*i + 1];//记录每个点的冲突点 opp[belong[2*i + 1]] = belong[2*i]; } if (flag) printf("NO\n"); else { printf("YES\n"); rbuild(); topsort(); for (i = 0; i < 2*n; i += 2) { if (col[belong[i]] == 1) { printf("%02d:%02d %02d:%02d\n",tm[i].s/60,tm[i].s%60,tm[i].e/60,tm[i].e%60); } else { printf("%02d:%02d %02d:%02d\n",tm[i + 1].s/60,tm[i + 1].s%60,tm[i + 1].e/60,tm[i + 1].e%60); } } } } int main() { // Read(); int i; int h1,m1,h2,m2,len; while (~scanf("%d",&n)) { for (i = 0; i < n; ++i) { scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&len); //printf("%d %d %d %d %d",h1,m1,h2,m2,len); tm[2*i].s = h1*60 + m1; tm[2*i].e = tm[2*i].s + len; tm[2*i + 1].e = h2*60 + m2; tm[2*i + 1].s = tm[2*i + 1].e - len; } build(); solve(); } return 0; }