2-SAT 输出可行解
找可行解的方案就是:
根据第一次建的图建一个反图..然后求逆拓扑排序,建反图的原因是保持冲突的两个事件肯定会被染成不同的颜色
求逆拓扑排序的原因也是为了对图染的色不会发生冲突,输出可行解就是遍历一次逆拓扑排序时染成的颜色,输出同一组颜色的解就是其中的一组可行解。
代码:
1 #include <stdio.h> 2 #include <iostream> 3 #include <string.h> 4 #include <stack> 5 #include <queue> 6 7 const int maxn = 2011; 8 const int maxm = 3000011; 9 struct node{ 10 int u; 11 int v; 12 int next; 13 }edge1[maxm], edge2[maxm]; 14 struct tt{ 15 int s; 16 int e; 17 int l; 18 }tim[maxn]; 19 int n, m, cnt1, cnt2, scc_cnt, dfs_clock; 20 int head1[maxn], head2[maxn], in[maxn], ct[maxn], ans[maxn]; 21 int sccno[maxn], dfn[maxn], low[maxn], color[maxn]; 22 std::stack<int>st; 23 24 void init(){ 25 cnt1 = 0; 26 cnt2 = 0; 27 scc_cnt = 0; 28 dfs_clock = 0; 29 memset(in, 0, sizeof(in)); 30 memset(ans, 0, sizeof(ans)); 31 memset(color, 0, sizeof(color)); 32 memset(sccno, 0, sizeof(sccno)); 33 memset(dfn, 0, sizeof(dfn)); 34 memset(low, 0, sizeof(low)); 35 memset(head1, -1, sizeof(head1)); 36 memset(head2, -1, sizeof(head2)); 37 } 38 39 void add(int u, int v, struct node edge[], int head[], int &cnt){ 40 edge[cnt].u = u; 41 edge[cnt].v = v; 42 edge[cnt].next = head[u]; 43 head[u] = cnt++; 44 } 45 46 void dfs(int u){ 47 low[u] = dfn[u] = ++dfs_clock; 48 st.push(u); 49 for(int i = head1[u]; i != -1; i = edge1[i].next){ 50 int v = edge1[i].v; 51 if(!dfn[v]){ 52 dfs(v); 53 low[u] = std::min(low[u], low[v]); 54 } 55 else if(!sccno[v]){ 56 low[u] = std::min(low[u], dfn[v]); 57 } 58 } 59 if(low[u]==dfn[u]){ 60 ++scc_cnt; 61 while(1){ 62 int x = st.top(); 63 st.pop(); 64 sccno[x] = scc_cnt; 65 if(x==u) break; 66 } 67 } 68 } 69 70 void toposort(){ 71 std::queue<int>qu; 72 for(int i = 1; i <= scc_cnt; i++){ 73 if(in[i]==0) qu.push(i); 74 } 75 while(!qu.empty()){ 76 int u = qu.front(); 77 qu.pop(); 78 if(color[u]==0){ 79 color[u] = 1; 80 color[ct[u]] = -1; 81 } 82 for(int i = head2[u]; i != -1; i = edge2[i].next){ 83 int v = edge2[i].v; 84 --in[v]; 85 if(in[v]==0) qu.push(v); 86 } 87 } 88 } 89 90 int main(){ 91 while(~scanf("%d", &n)){ 92 init(); 93 for(int i = 0; i < n; i++){ 94 int s1, s2, t1, t2, l; 95 int sb = scanf("%d:%d %d:%d %d", &s1, &s2, &t1, &t2, &l); 96 sb++; 97 tim[i].s = s1*60+s2; 98 tim[i].e = t1*60+t2; 99 tim[i].l = l; 100 } 101 for(int i = 0; i < n; i++){ 102 for(int j = 0; j < n; j++){ 103 if(i!=j){ 104 if(tim[i].s<tim[j].s+tim[j].l && tim[j].s<tim[i].s+tim[i].l) add(i<<1, j<<1|1, edge1, head1, cnt1); 105 if(tim[i].s<tim[j].e && tim[j].e-tim[j].l<tim[i].s+tim[i].l) add(i<<1, j<<1, edge1, head1, cnt1); 106 if(tim[i].e-tim[i].l<tim[j].s+tim[j].l && tim[j].s<tim[i].e) add(i<<1|1, j<<1|1, edge1, head1, cnt1); 107 if(tim[i].e-tim[i].l<tim[j].e && tim[j].e-tim[j].l<tim[i].e) add(i<<1|1, j<<1, edge1, head1, cnt1); 108 } 109 } 110 } 111 for(int i = 0; i < n+n; i++){ 112 if(!dfn[i]) dfs(i); 113 } 114 for(int i = 0; i < n+n; i++){ 115 for(int j = head1[i]; j != -1; j = edge1[j].next){ 116 int v = edge1[j].v; 117 if(sccno[i] != sccno[v]){ 118 add(sccno[v], sccno[i], edge2, head2, cnt2); 119 in[sccno[i]]++; 120 } 121 } 122 } 123 bool flag = false; 124 for(int i = 0; i < n; i++){ 125 if(sccno[i<<1]==sccno[i<<1|1]){ 126 flag = true; 127 break; 128 } 129 ct[sccno[i<<1]] = sccno[i<<1|1]; 130 ct[sccno[i<<1|1]] = sccno[i<<1]; 131 } 132 133 if(flag) puts("NO"); 134 else{ 135 toposort(); 136 for(int i = 0; i < n+n; i++){ 137 if(color[sccno[i]]==1) ans[i] = 1; 138 } 139 puts("YES"); 140 for(int i = 0; i < n; i++) { 141 if(ans[i<<1]) printf("%02d:%02d %02d:%02d\n", tim[i].s/60, tim[i].s%60, (tim[i].s+tim[i].l)/60, (tim[i].s+tim[i].l)%60); 142 else printf("%02d:%02d %02d:%02d\n", (tim[i].e-tim[i].l)/60, (tim[i].e-tim[i].l)%60, tim[i].e/60, tim[i].e%60); 143 } 144 } 145 } 146 return 0; 147 }