原题模型:两者(A,B)不能同时取

  1 #include "cstdio"
  2 #include "vector"
  3 #include "stack"
  4 #include "cstring"
  5 using namespace std;
  6 #define maxn 2010
  7
  8 int n,N,dfs_clock,scc_cnt,v,tt=0;
  9 char st[10];
 10 int S[maxn],T[maxn],D[maxn],pre[maxn],sccno[maxn],lowlink[maxn],id[maxn],cfl[maxn],color[maxn],done[maxn];
 11 int G[maxn][maxn],G2[maxn][maxn];
 12 stack<int> St;
 13
 14 void tarjan(int u)
 15 {
 16     pre[u]=lowlink[u]=++dfs_clock;
 17     St.push(u);
 18     for (int i=1;i<=G[u][0];i++)
 19     {
 20         int v=G[u][i];
 21         if (!pre[v])
 22         {
 23             tarjan(v);
 24             lowlink[u]=min(lowlink[u],lowlink[v]);
 25         }
 26         else if (!sccno[v])
 27         {
 28             lowlink[u]=min(lowlink[u],pre[v]);
 29         }
 30     }
 31     if (lowlink[u]==pre[u])
 32     {
 33         scc_cnt++;
 34         for (;;)
 35         {
 36             int x=St.top();
 37             St.pop();
 38             sccno[x]=scc_cnt;
 39             if (x==u) break;
 40         }
 41     }
 42 }
 43
 44 void find_scc(int n)
 45 {
 46     dfs_clock=scc_cnt=0;
 47     memset(sccno,0,sizeof(sccno));
 48     memset(pre,0,sizeof(pre));
 49     for (int i=1;i<=n;i++)
 50         if (!pre[i])
 51             tarjan(i);
 52 }
 53
 54 void add_edge(int x,int y)
 55 {
 56     G[x][0]++;
 57     G[x][G[x][0]]=y;
 58 }
 59
 60 void _add_edge(int x,int y)
 61 {
 62     G2[x][0]++;
 63     G2[x][G2[x][0]]=y;
 64 }
 65
 66 void solve()
 67 {
 68     //1->N:x[i]        N+1->2N:not x[i]
 69     v=N*2;
 70     for (int i=1;i<=N;i++)
 71     {
 72         for (int j=i+1;j<=N;j++)
 73         {
 74             if (min(S[i]+D[i],S[j]+D[j])>max(S[i],S[j]))    //事件i和j不能同时满足,连边
 75             {
 76                 add_edge(i,N+j);
 77                 add_edge(j,N+i);
 78             }
 79             if (min(S[i]+D[i],T[j])>max(S[i],T[j]-D[j]))
 80             {
 81                 add_edge(i,j);
 82                 add_edge(N+j,N+i);
 83             }
 84             if (min(T[i],S[j]+D[j])>max(T[i]-D[i],S[j]))
 85             {
 86                 add_edge(N+i,N+j);
 87                 add_edge(j,i);
 88             }
 89             if (min(T[i],T[j])>max(T[i]-D[i],T[j]-D[j]))
 90             {
 91                 add_edge(N+i,j);
 92                 add_edge(N+j,i);
 93             }
 94         }
 95     }
 96 }
 97
 98 void topsort(int x)
 99 {
100     int j;
101     id[x] = -1;
102     done[++tt]=x;
103     for(int k=1;k<=G2[x][0];k++)
104     {
105         j = G2[x][k];
106         id[j]--;
107         if( id[j] == 0 ) topsort( j );
108     }
109 }
110
111 void dfs( int i )
112 {
113     int j;
114     color[i] = 2;
115     for(int k=1;k<=G[i][0];k++)
116     {
117         j = G2[i][k];
118         if( color[j] == 0 ) dfs( j );
119     }
120 }
121
122 void print( int aa, int bb )
123 {
124     if( aa / 60 < 10 ) printf( "0" );
125     printf( "%d:", aa / 60 );
126     if( aa % 60 < 10 ) printf( "0" );
127     printf( "%d ", aa % 60 );
128     if( bb / 60 < 10 ) printf( "0" );
129     printf( "%d:", bb / 60 );
130     if( bb % 60 < 10 ) printf( "0" );
131     printf( "%d\n", bb % 60 );
132 }
133
134 int main()
135 {
136     scanf("%d",&N);
137     for( int i = 1; i <= N; i++ )       //时间统一转化成分钟存储
138     {
139         scanf( "%s", st );
140         S[i] = ( st[0]-48 )*600 + ( st[1]-48 )*60;
141         S[i] += ( st[3]-48 )*10 + st[4]-48;
142         scanf( "%s", st );
143         T[i] = ( st[0]-48 )*600 + ( st[1]-48 )*60;
144         T[i] += ( st[3]-48 )*10 + st[4]-48;
145         scanf( "%d", &D[i] );
146     }
147
148     solve();
149     find_scc(2*N);
150
151     for (int i=1;i<=N;i++)
152     {
153         if (sccno[i]==sccno[N+i])
154         {
155             printf("NO\n");
156             return 0;
157         }
158     }
159
160     //printf("YES\n");
161     for (int i=1;i<=2*N;i++)        //强连通分量缩点并对块反向连边
162     {
163         for (int j=1;j<=G[i][0];j++)
164         {
165             int tm=G[i][j];
166             if (sccno[i]!=sccno[tm])
167             {
168                 _add_edge(sccno[tm],sccno[i]);
169                 id[sccno[i]]++;
170             }
171         }
172     }
173     for (int i=1;i<=scc_cnt;i++)    //对缩点之后的块拓扑排序,
174         if (id[i]==0)
175             topsort(i);
176
177     for( int i = 1; i <= N; i++ )
178     {
179         cfl[ sccno[i] ] = sccno[i+N];
180         cfl[ sccno[i+N] ] = sccno[i];
181     }
182
183     for( int ii = 1; ii <= scc_cnt; ii++ )      //按拓扑序对块染色,求方案
184     {
185         int i = done[ii];           //done[]:拓扑序列
186         if( color[i] != 0 ) continue;
187         color[i] = 1;               //color[]=1:选刚开始的时段,S~S+D
188         dfs( cfl[i] );              //color[]=2:选结束的时段,T-D~T
189     }
190     printf("YES\n");
191     for( int i = 1; i <= N; i++ )
192         if( color[ sccno[i] ] == 1 )
193             print( S[i], S[i]+D[i] );
194         else
195             print( T[i]-D[i], T[i] );
196
197     return 0;
198 }
199
200
201
202
203 //一直觉得ICPC不应该是种功利性的东西,那样就彻底变味了,也没意义了
204 //今年要干就好好干吧,也许明年就不打了
205 //没办法,有些事太复杂
206 //反正个人认为几个真心的朋友比所谓的成绩重要得多得多。
207 //。
208 //就这样吧

转载于:https://www.cnblogs.com/pdev/p/4059706.html

poj 3683 2-SAT入门相关推荐

  1. POJ 3683 【2-sat+求一组可行解】.cpp

    题意: 有一个牧师要给好几对新婚夫妇准备婚礼.. 已知每对新婚夫妇的有空的时间以及婚礼持续时间.. 问是否可以让每对新婚夫妇都得到该牧师的祝福~ 如果可以就输出YES以及可行解 不可以就输出NO 输入 ...

  2. POJ 3683 Priest John's Busiest Day(2-ST)

    题目链接:http://poj.org/problem?id=3683 题意:有n个婚礼要举行,但是只有一个牧师.第i个婚礼使用牧师的时间长为leni,可以在开始时或结束时使用.问能否使得n个婚礼均举 ...

  3. Bailian2714 求平均年龄(POJ NOI0105-01)【入门】

    问题链接:POJ NOI0105-01 求平均年龄. 求平均年龄 总时间限制: 1000ms 内存限制: 65536kB 描述 班上有学生若干名,给出每名学生的年龄(整数),求班上所有学生的平均年龄, ...

  4. [题解]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 ...

  5. POJ - 3683 Priest John's Busiest Day(2-SAT+路径打印)

    题目链接:点击查看 题目大意:现在有n对新人要结婚,每一场婚礼都要请牧师主持一个特殊的仪式,这个仪式必须在婚礼的前d分钟或者最后d分钟进行,现在问能否有一种安排,能让牧师参加到每一场婚礼去主持仪式,输 ...

  6. [2-sat专练]poj 3683,hdu 1814,hdu 1824,hdu 3622,hdu 4115,hdu 4421

    文章目录 Priest John's Busiest Day code Peaceful Commission code Let's go home code Bomb Game code Elimi ...

  7. POJ 3683 Priest John's Busiest Day (算竞进阶习题)

    2-SAT 可以把每一次仪式看成变量,0/1的取值分别为开头举行和结尾举行. 转换为2-SAT接受的命题,就是看某一次仪式中有没有重合的时间段,有的话,就按照不冲突的形式连有向边. 然后跑tarjan ...

  8. POJ 3683 Priest John's Busiest Day

    2-SAT简单题,判断一下两个开区间是否相交 #include<cstdio> #include<cstring> #include<cmath> #include ...

  9. poj 2382 Apple Catching 入门dp

    点击打开链接 #include <iostream> #include <algorithm> using namespace std; const int M =1010; ...

  10. Team Silver_Bullet 训练记录

    Team members Vec Grunt henryrabbit To do list team:起队名 每周组队训练 补题 Vec: Grunt:切题,切题,切更多的题!做好切所有类型题的觉悟! ...

最新文章

  1. leetcode第二题java_LeetCode第二题,Java实现
  2. java编写数字金字塔_用JAVA写数字金字塔
  3. Ocelot中文文档-缓存
  4. jstl sql标签使用
  5. STL 中的 accumulate(C++)
  6. 【kafka】已解决 kafka No current assignment for partition
  7. 小程序入门学习04--数据绑定、条件渲染、列表渲染
  8. Weblogic常用监控指标
  9. python 进化树_Biopython之系统发育树(进化树)的绘制
  10. [教程]安装系统解码器 - 指导教程
  11. AST使用eval运行函数,更换数值
  12. 互动派年会-comsol专题超强干货剖析
  13. 2015年微信营销趋势分析与归纳!
  14. Linux下Docker安装微信文件传输问题
  15. 瓜瓜的时空旅行,第三次模拟赛,dfs序+线段树维护最小值
  16. EasyPoi 实现Word文档内容替换3种情况(正常文本替换、表格文本替换、图表替换)
  17. 去哪儿网2015春季校招笔试--回忆版
  18. 下载refseq序列
  19. 模仿淘宝web扫码登录
  20. nyistOJ-See LCS again(二分)

热门文章

  1. win和linux下DBI安装手册
  2. 未来人在数据分析中的角色转变
  3. KeyShot中该怎么添加反射地平面
  4. 很喜欢博客园这个平台
  5. 打造极致Material Design动画风格Button
  6. JSON stringify and parse
  7. Linux---Samba文件共享服务
  8. MOSS2007匿名调查列表使用分页符导致的错误分析
  9. 17_购物车删除商品与清空购物车
  10. android:gravity与android:layout_gravity的区别,以及代码设置对应属性