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 }

 

posted @ 2014-10-21 15:18  Naturain  阅读(150)  评论(0)    收藏  举报