Poj--3683(2-SAT,拓扑排序,输出解)
2014-10-21 15:12:37
思路:自己断断续续搞了差不多两个小时吧,把这题A掉,2-sat也学的差不多了。
做法就是把每个婚礼看成连个点,i 和 i' 分别表示牧师在婚礼开始时祝福、在婚礼结束时祝福。于是我们就能获得每个婚礼的两个祝福时间段。两层循环扫一遍每两个婚礼,判断他们两个时间段是否重合,如果重合,则建“必须”边。(如:A和B’时间段有重合部分(即A在婚礼开始祝福和B在婚礼结束祝福的两个时间段有重合),那么建边:A->B,B'->A'),由于每个婚礼自己会和自己重合,所以要判断一下。
1 /************************************************************************* 2 > File Name: 3683.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Mon 20 Oct 2014 09:57:49 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 2010; 27 28 int N; 29 int first[maxn],next[maxn * maxn],ver[maxn * maxn],ecnt; 30 int f1[maxn],n1[maxn * maxn],v1[maxn * maxn],e1; 31 int low[maxn],dfn[maxn],sc[maxn],asc[maxn],scnt,tot; 32 int din[maxn],col[maxn]; 33 stack<int> S; 34 queue<int> Q; 35 36 struct time{ 37 int s,t; 38 int sh,sm,th,tm; 39 int sd,td; 40 }t[maxn]; 41 42 void Add_edge(int u,int v){ 43 next[++ecnt] = first[u]; 44 ver[ecnt] = v; 45 first[u] = ecnt; 46 } 47 48 void Build_graph(){ 49 for(int i = 0; i < N; ++i){ 50 for(int j = 0; j < N; ++j){ 51 if(i == j) continue; 52 if(min(t[i].sd,t[j].sd) - max(t[i].s,t[j].s) > 0){ 53 Add_edge(i * 2,j * 2 + 1); 54 Add_edge(j * 2,i * 2 + 1); 55 } 56 if(min(t[i].t,t[j].t) - max(t[i].td,t[j].td) > 0){ 57 Add_edge(i * 2 + 1,j * 2); 58 Add_edge(j * 2 + 1,i * 2); 59 } 60 if(min(t[i].sd,t[j].t) - max(t[i].s,t[j].td) > 0){ 61 Add_edge(i * 2,j * 2); 62 Add_edge(j * 2 + 1,i * 2 + 1); 63 } 64 if(min(t[i].t,t[j].sd) - max(t[i].td,t[j].s) > 0){ 65 Add_edge(i * 2 + 1,j * 2 + 1); 66 Add_edge(j * 2,i * 2); 67 } 68 } 69 } 70 } 71 72 void Dfs(int p){ 73 dfn[p] = low[p] = ++tot; 74 S.push(p); 75 for(int i = first[p]; i != -1; i = next[i]){ 76 int v = ver[i]; 77 if(!dfn[v]){ 78 Dfs(v); 79 low[p] = min(low[p],low[v]); 80 } 81 else if(!sc[v]){ 82 low[p] = min(low[p],dfn[v]); 83 } 84 } 85 if(low[p] == dfn[p]){ 86 ++scnt; 87 while(1){ 88 int x = S.top(); 89 S.pop(); 90 sc[x] = scnt; 91 if(x == p) break; 92 } 93 } 94 } 95 96 void Tarjan(){ 97 memset(dfn,0,sizeof(dfn)); 98 memset(low,0,sizeof(low)); 99 memset(sc,0,sizeof(sc)); 100 memset(asc,0,sizeof(asc)); 101 scnt = tot = 0; 102 while(!S.empty()) S.pop(); 103 for(int i = 0; i < 2 * N; ++i) 104 if(!dfn[i]) Dfs(i); 105 } 106 107 void Add_edge1(int u,int v){ 108 n1[++e1] = f1[u]; 109 v1[e1] = v; 110 f1[u] = e1; 111 } 112 113 void Build_dag(){ 114 for(int i = 0; i < 2 * N; ++i){ 115 for(int j = f1[i]; j != -1; j = next[j]){ 116 int v = ver[j]; 117 if(sc[i] != sc[v]){ 118 Add_edge1(sc[v],sc[i]); 119 din[sc[i]]++; 120 } 121 } 122 } 123 } 124 125 void Toposort(){ 126 while(!Q.empty()) Q.pop(); 127 for(int i = 1; i <= scnt; ++i) 128 if(din[i] == 0) Q.push(i); 129 while(!Q.empty()){ 130 int x = Q.front(); 131 Q.pop(); 132 if(!col[x]){ 133 col[x] = 1; 134 col[asc[x]] = 2; 135 } 136 for(int i = f1[x]; i != -1; i = n1[i]){ 137 int v = v1[i]; 138 din[v]--; 139 if(din[v] == 0) Q.push(v); 140 } 141 } 142 } 143 144 void Init(){ 145 memset(first,-1,sizeof(first)); 146 memset(f1,-1,sizeof(f1)); 147 memset(din,0,sizeof(din)); 148 memset(col,0,sizeof(col)); 149 ecnt = 0; 150 e1 = 0; 151 } 152 153 int main(){ 154 int d; 155 Init(); 156 scanf("%d",&N); 157 for(int i = 0; i < N; ++i){ 158 scanf("%d:%d %d:%d %d",&t[i].sh,&t[i].sm,&t[i].th,&t[i].tm,&d); 159 t[i].s = t[i].sh * 60 + t[i].sm; 160 t[i].t = t[i].th * 60 + t[i].tm; 161 t[i].sd = t[i].s + d; 162 t[i].td = t[i].t - d; 163 } 164 Build_graph(); 165 Tarjan(); 166 Build_dag(); 167 int flag = 1; 168 for(int i = 0; i < 2 * N; i += 2){ 169 if(sc[i] == sc[i + 1]){ 170 flag = 0; 171 break; 172 } 173 asc[sc[i]] = sc[i + 1]; 174 asc[sc[i + 1]] = sc[i]; 175 } 176 if(flag){ 177 printf("YES\n"); 178 Toposort(); 179 int f; 180 for(int i = 0; i < 2 * N; i += 2){ 181 if(col[sc[i]] == 1){ 182 printf("%02d:%02d %02d:%02d\n",t[i/2].sh,t[i/2].sm,t[i/2].sd/60,t[i/2].sd%60); 183 } 184 else{ 185 printf("%02d:%02d %02d:%02d\n",t[i/2].td/60,t[i/2].td%60,t[i/2].th,t[i/2].tm); 186 } 187 } 188 } 189 else printf("NO\n"); 190 return 0; 191 }

浙公网安备 33010602011771号