poj 3683 Priest John's Busiest Day (2-sat 模版)

 http://poj.org/problem?id=3683

 

题意:

有n个婚礼,每个婚礼有起始时间si,结束时间ti,还有一个主持时间ti,ti必须安排在婚礼的开始或者结束,

主持由祭祀来做,但是只有一个祭祀,所以 各个婚礼的主持时间不能重复,问你有没有可能正常的安排主持时间,

不能输出no,能的话要输出具体的答案:即每个婚礼的主持时间段是什么样的。

 

2-sat 问题。建图:

对于每个婚礼,主持时间只有两种状态,而且各个婚礼之间的主持时间之间有相互限制,自然想到2-sat。

对于婚礼i和婚礼j。i表示在开始主持,i2表示在结束主持,j类似。

枚举每一对不同的i和j。

如果i和j冲突。连接i j2

如果i和j2冲突,连接i j

如果i2和j冲突,连接i2 j2

如果i2和j2冲突,连接i2 j

然后就是Tarjan求强联通,判断2-sat问题,成立的话,topsort,输出答案。



  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include< set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include< string>
 11  #define Min(a,b) a<b?a:b
 12  #define Max(a,b) a>b?a:b
 13  #define CL(a,num) memset(a,num,sizeof(a));
 14  #define eps  1e-12
 15  #define inf 100000000
 16  #define mx 1<<60
 17  #define ll   __int64
 18  const  double pi  = acos(- 1.0);
 19  const  int maxn =  1200;
 20  using  namespace std;
 21  int  top,num,bcnt,belong[maxn* 2],instack[maxn* 2],stack[maxn* 2],dfn[maxn* 2],low[maxn* 2];
 22  int n ,m;
 23  int opp[maxn *  2],col[maxn *  2], in[maxn* 2],head[maxn* 2];
 24  int ans[maxn* 2] ;
 25  struct pnode
 26 {
 27      int  from ;
 28      int to;
 29      int next;
 30 }p[maxn*maxn],eg[maxn*maxn];
 31 
 32  int cnt ,next[maxn* 2];
 33  void add( int u, int v)
 34 {
 35     p[cnt]. from = u;
 36     p[cnt].to = v;
 37     p[cnt].next  = next[u];
 38     next[u] = cnt++;
 39 
 40 }
 41 
 42  void tarjan( int i) // tarjan  求强联通 分量
 43  {
 44      int j,k;
 45     dfn[i] = low[i] = ++num;
 46     stack[++top] = i;
 47     instack[i] =  1;
 48      for(k = next[i] ; k != - 1;k = p[k].next)
 49     {
 50 
 51          j = p[k].to ;
 52          if(!dfn[j])
 53         {
 54             tarjan(j);
 55              if(low[j] < low[i]) low[i] = low[j] ;
 56         }
 57          else
 58         {
 59              if(instack[j] && dfn[j] < low[i]) low[i] = dfn[j] ;
 60         }
 61 
 62     }
 63      if(dfn[i] == low[i])
 64     {
 65         bcnt++;
 66          do
 67         {
 68             j = stack[top--];
 69             instack[j] =  0 ;
 70             belong[j] = bcnt ;
 71         } while(j != i);
 72     }
 73 }
 74  void insert( int u, int v)
 75 {
 76     eg[num]. from = u;
 77     eg[num].to = v;
 78     eg[num].next = head[u];
 79     head[u] = num++;
 80 }
 81  bool  solve() // tarjan  + topsort染色输出
 82  {
 83      int i, l;
 84      for(i = 0 ; i <= n* 2;i++)
 85     {
 86         dfn[i] = low[i] = instack[i] = stack[i] = belong[i] =  0;
 87     }
 88     top = bcnt = num =  0;
 89      for(i =  0 ; i < n* 2;i++)
 90     {
 91          if(!dfn[i])tarjan(i);
 92     }
 93      for(i = 0 ;i< n;i++)
 94     {
 95          if(belong[i] == belong[i + n])  return  false ; // 判断是否 有解
 96 
 97         opp[belong[i]] = belong[i + n]; // 记录 对立 点的位置 
 98          opp[belong[i+n]] = belong[i] ;
 99     }
100     // 下面重新构图
101      CL(col, 0);
102     CL( in, 0);
103     CL(head,- 1);
104     num =  0;
105       for(i =  0 ; i < cnt ;i++)
106      {
107           if(belong[p[i]. from] != belong[p[i].to])
108          {
109              insert(belong[p[i].to],belong[p[i]. from]); //   (将 缩点 )反向建图 
110                in[belong[p[i]. from]]++; // 记录每个点的入度
111           }
112      }
113      queue< int>que;
114       for(i =  0 ;i < bcnt;i++) // 将入度为0 的点 入队列
115       {
116           if( in[i] ==  0) {que.push(i);}
117      }
118       while(!que.empty())
119      {
120           int k = que.front();que.pop();
121 
122           if(col[k] ==  0)
123          {
124              col[k] =  1; // 染为 红色 
125               col[opp[k]] = - 1; //   将 对立点染为 绿色
126 
127 
128          }
129            for(i = head[k];i!=- 1;i = eg[i].next)
130              {
131                  int v = eg[i].to;
132                  in[v]--;
133                  if( in[v] ==  0)que.push(v) ;
134 
135              }
136 
137 
138      }
139       CL(ans, 0);
140       for(i =  0 ; i <  2*n;i++)
141      {
142           if(col[belong[i]] ==  1) // 标记 染为 红色的 点  ,
143           {
144              ans[i] =  1;
145          }
146      }
147 
148     return   true;
149 
150 
151 }
152  void init()
153 {
154     CL(next,- 1);
155     cnt =  0 ;
156 
157 }
158  struct node
159 {
160      int   from;
161      int   to;
162      int len ;
163 }q[maxn] ;
164  int judge(  char *c)
165 {
166      int a,b;
167     sscanf(c, " %d:%d ",&a,&b);
168 
169      return a* 60 + b ;
170 
171 
172 }
173  int judge1( int a, int b, int c, int d)
174 {
175 
176     if(b <= c || d <= a)  return  0;
177 
178      return  1;
179 }
180  void pf( int x)
181 {
182     printf( " %02d:%02d ",x/ 60,x% 60) ;
183 }
184  int main()
185 {
186      int i,j,a,b,c;
187 
188      // freopen("data.txt","r",stdin) ;
189       char str1[ 10],str2[ 10];
190       while(scanf( " %d ",&n)!=EOF)
191      {
192          init() ;
193          for(i =  0;i < n;i++)
194         {
195             scanf( " %s %s %d ",str1,str2,&q[i].len);
196 
197             q[i]. from = judge(str1);
198 
199             q[i].to = judge(str2);
200 
201 
202 
203 
204         }
205 
206          for(i =  0 ;i < n;i++)
207         {
208              for(j =   0;j < n;j++)
209             {
210                      if(i == j) continue ;
211                  if(judge1(q[i]. from,q[i]. from + q[i].len,q[j]. from,q[j]. from + q[j].len))
212                 {
213                         add(i,j+n);
214 
215 
216 
217                 }
218                   if(judge1(q[i]. from,q[i]. from + q[i].len,q[j].to - q[j].len,q[j].to ))
219                 {
220                         add(i,j);
221 
222 
223 
224                 }
225                   if(judge1(q[i].to - q[i].len,q[i].to,q[j]. from,q[j]. from + q[j].len))
226                 {
227                         add(i + n,j+n);
228 
229 
230 
231                 }
232                   if(judge1(q[i].to - q[i].len,q[i].to,q[j].to - q[j].len,q[j].to ))
233                 {
234                         add(i + n,j);
235 
236 
237 
238                 }
239             }
240         }
241 
242          bool  f = solve();
243          if(f)
244         {
245             puts( " YES ");
246               for(i = 0 ; i< n;i++)
247              {
248                   if(ans[i])
249                  {
250                      pf(q[i]. from);printf( "   ");
251                      pf(q[i]. from + q[i].len);
252                      puts( "");
253                  }
254                   else
255                  {
256                       pf(q[i].to - q[i].len);printf( "   ");
257                       pf(q[i].to);
258                       puts( "");
259                  }
260              }
261         }
262          else puts( " NO ");
263 
264      }
265 }

你可能感兴趣的:(poj)