[题解]POJ 3683 Priest John's Busiest Day

【Description】

John is the only priest in his town. September 1st is the John's busiest day in a year because there is an old legend in the town that the couple who get married on that day will be forever blessed by the God of Love. This year N couples plan to get married on the blessed day. The i-th couple plan to hold their wedding from time Si to time Ti. According to the traditions in the town, there must be a special ceremony on which the couple stand before the priest and accept blessings. The i-th couple need Di minutes to finish this ceremony. Moreover, this ceremony must be either at the beginning or the ending of the wedding (i.e. it must be either from Si to Si + Di, or from Ti - Di to Ti). Could you tell John how to arrange his schedule so that he can present at every special ceremonies of the weddings.

Note that John can not be present at two weddings simultaneously.

【Input】

The first line contains a integer N ( 1 ≤ N ≤ 1000).
The next N lines contain the Si, Ti and Di. Si and Ti are in the format of hh:mm.

【Output】

The first line of output contains "YES" or "NO" indicating whether John can be present at every special ceremony. If it is "YES", output another N lines describing the staring time and finishing time of all the ceremonies.

【Sample Input】

2
08:00 09:00 30
08:15 09:00 20

【Sample Output】

YES
08:00 08:30
08:40 09:00

---------------------------------------------------------------------------------------------------------------------------------

【题目大意】
有n场婚礼,每场婚礼有对应的开始和结束时间,每场婚礼都需要举行一场仪式,仪式持续时间为Di。仪式可以在婚礼前举行[Si,Si+Di],或者在婚礼后举行[Ti-Di,Ti]。要求每个婚礼的仪式不冲突,求一组仪式时间安排的可行解。
【题解】
裸的2-SAT问题。主要是建图,注意判断哪些方案会出现矛盾。其它为2-SAT的基础代码。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 using namespace std;
  6 #define MAXN 1020*2
  7 int n;
  8 struct Thing
  9 {
 10     int st,ed,Len;
 11 }p[MAXN];
 12 struct node
 13 {
 14     int v;
 15     node *next;
 16 };
 17 node edge[MAXN*MAXN];
 18 node *cnt=&edge[0];
 19 node *adj[MAXN];
 20 node edge2[MAXN*MAXN];
 21 node *cnt2=&edge2[0];
 22 node *adj2[MAXN];
 23 int dfn[MAXN],low[MAXN],dcnt;
 24 int Belong[MAXN],Num[MAXN];
 25 int stack[MAXN],top;
 26 int In[MAXN],opp[MAXN],scc;
 27 int q[MAXN],col[MAXN];
 28 bool Instack[MAXN],ans[MAXN];
 29 char s1[10],s2[10];
 30 inline void Addedge(int u,int v)
 31 {
 32     node *p=++cnt;
 33     p->v=v;
 34     p->next=adj[u];
 35     adj[u]=p;
 36 }
 37 inline void Addedge2(int u,int v)
 38 {
 39     node *p=++cnt2;
 40     p->v=v;
 41     p->next=adj2[u];
 42     adj2[u]=p;
 43 }
 44 inline int Cal(char str[])
 45 {
 46     int Ret=((str[0]-'0')*10+str[1]-'0')*60+(str[3]-'0')*10+str[4]-'0';
 47     return Ret;
 48 }
 49 inline bool Check(int st1,int len1,int st2,int len2)
 50 {
 51     return (st2<st1+len1)&&(st1<st2+len2);
 52 }
 53 void Read()
 54 {
 55     //scanf("%d",&n);
 56     int i;
 57     for(i=1;i<=n;i++)
 58     {
 59         scanf("%s%s%d",s1,s2,&p[i].Len);
 60         p[i].st=Cal(s1);
 61         p[i].ed=Cal(s2);
 62     }
 63 }
 64 void Build_map()
 65 {
 66     int i,j;
 67     for(i=1;i<=n;i++)
 68         for(j=1;j<=n;j++)
 69         {
 70             if(i==j)
 71                 continue;
 72             if(Check(p[i].st,p[i].Len,p[j].st,p[j].Len))
 73                 Addedge(i,j+n);
 74             if(Check(p[i].st,p[i].Len,p[j].ed-p[j].Len,p[j].Len))
 75                 Addedge(i,j);
 76             if(Check(p[i].ed-p[i].Len,p[i].Len,p[j].st,p[j].Len))
 77                 Addedge(i+n,j+n);
 78             if(Check(p[i].ed-p[i].Len,p[i].Len,p[j].ed-p[j].Len,p[j].Len))
 79                 Addedge(i+n,j);
 80         }
 81 }
 82 void Tarjan(int u)
 83 {
 84     int v;
 85     dfn[u]=low[u]=++dcnt;
 86     stack[++top]=u;
 87     Instack[u]=true;
 88     for(node *p=adj[u];p;p=p->next)
 89     {
 90         v=p->v;
 91         if(!dfn[v])
 92         {
 93             Tarjan(v);
 94             low[u]=min(low[u],low[v]);
 95         }
 96         else if(Instack[v])
 97             low[u]=min(low[u],dfn[v]);
 98     }
 99     if(dfn[u]==low[u])
100     {
101         scc++;
102         do
103         {
104             v=stack[top];
105             top--;
106             Instack[v]=false;
107             Belong[v]=scc;
108             Num[scc]++;
109         }while(v!=u);
110     }
111 }
112 bool Work()
113 {
114     int i;
115     for(i=1;i<=n*2;i++)
116         if(!dfn[i])
117             Tarjan(i);
118     for(i=1;i<=n;i++)
119     {
120         if(Belong[i]==Belong[i+n])
121             return false;
122         opp[Belong[i]]=Belong[i+n];
123         opp[Belong[i+n]]=Belong[i];
124     }
125     int u,v;
126     for(i=1;i<=n*2;i++)
127         for(node *p=adj[i];p;p=p->next)
128         {
129             v=p->v;
130             if(Belong[i]!=Belong[v])
131             {
132                 Addedge2(Belong[v],Belong[i]);
133                 In[Belong[i]]++;
134             }
135         }
136     int l=0,r=0;
137     for(i=1;i<=scc;i++)
138         if(!In[i])
139         {
140             q[r]=i;
141             r++;
142         }
143     while(l<r)
144     {
145         u=q[l];
146         l++;
147         if(!col[u])
148         {
149             col[u]=1;
150             col[opp[u]]=-1;
151         }
152         for(node *p=adj2[u];p;p=p->next)
153         {
154             v=p->v;
155             In[v]--;
156             if(!In[v])
157             {
158                 q[r]=v;
159                 r++;
160             }
161         }
162     }
163     for(i=1;i<=n;i++)
164         if(col[Belong[i]]==1)
165             ans[i]=true;
166     return true;
167 }
168 void Print()
169 {
170     if(Work())
171     {
172         printf("YES\n");
173         int i;
174         for(i=1;i<=n;i++)
175         {
176             if(ans[i])
177                 printf("%02d:%02d %02d:%02d\n",p[i].st/60,p[i].st%60,(p[i].st+p[i].Len)/60,(p[i].st+p[i].Len)%60);
178             else
179                 printf("%02d:%02d %02d:%02d\n",(p[i].ed-p[i].Len)/60,(p[i].ed-p[i].Len)%60,p[i].ed/60,p[i].ed%60);
180         }
181     }
182     else
183         printf("NO\n");
184 }
185 inline void Pre()
186 {
187     memset(edge,0,sizeof(edge));
188     memset(adj,0,sizeof(adj));
189     cnt=&edge[0];
190     memset(edge2,0,sizeof(edge2));
191     memset(adj2,0,sizeof(adj2));
192     cnt2=&edge2[0];
193     memset(dfn,0,sizeof(dfn));
194     memset(low,0,sizeof(low));
195     dcnt=0;
196     top=0;
197     memset(Instack,false,sizeof(Instack));
198     memset(Belong,0,sizeof(Belong));
199     memset(Num,0,sizeof(Num));
200     scc=0;
201     memset(opp,0,sizeof(opp));
202     memset(In,0,sizeof(In));
203     memset(q,0,sizeof(q));
204     memset(col,0,sizeof(col));
205     memset(ans,false,sizeof(ans));
206 }
207 int main()
208 {
209     //freopen("Data.in","r",stdin);
210     //freopen("Data.out","w",stdout);
211     while(scanf("%d",&n)!=EOF)
212     {
213         Pre();
214         Read();
215         Build_map();
216         Print();
217     }
218     return 0;
219 }

 

转载于:https://www.cnblogs.com/CQBZOIer-zyy/archive/2013/01/22/2872211.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值