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

 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 }
原文地址:https://www.cnblogs.com/acSzz/p/2672465.html