poj 3683 2-SAT入门
原题模型:两者(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入门相关推荐
- POJ 3683 【2-sat+求一组可行解】.cpp
题意: 有一个牧师要给好几对新婚夫妇准备婚礼.. 已知每对新婚夫妇的有空的时间以及婚礼持续时间.. 问是否可以让每对新婚夫妇都得到该牧师的祝福~ 如果可以就输出YES以及可行解 不可以就输出NO 输入 ...
- POJ 3683 Priest John's Busiest Day(2-ST)
题目链接:http://poj.org/problem?id=3683 题意:有n个婚礼要举行,但是只有一个牧师.第i个婚礼使用牧师的时间长为leni,可以在开始时或结束时使用.问能否使得n个婚礼均举 ...
- Bailian2714 求平均年龄(POJ NOI0105-01)【入门】
问题链接:POJ NOI0105-01 求平均年龄. 求平均年龄 总时间限制: 1000ms 内存限制: 65536kB 描述 班上有学生若干名,给出每名学生的年龄(整数),求班上所有学生的平均年龄, ...
- [题解]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 ...
- POJ - 3683 Priest John's Busiest Day(2-SAT+路径打印)
题目链接:点击查看 题目大意:现在有n对新人要结婚,每一场婚礼都要请牧师主持一个特殊的仪式,这个仪式必须在婚礼的前d分钟或者最后d分钟进行,现在问能否有一种安排,能让牧师参加到每一场婚礼去主持仪式,输 ...
- [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 ...
- POJ 3683 Priest John's Busiest Day (算竞进阶习题)
2-SAT 可以把每一次仪式看成变量,0/1的取值分别为开头举行和结尾举行. 转换为2-SAT接受的命题,就是看某一次仪式中有没有重合的时间段,有的话,就按照不冲突的形式连有向边. 然后跑tarjan ...
- POJ 3683 Priest John's Busiest Day
2-SAT简单题,判断一下两个开区间是否相交 #include<cstdio> #include<cstring> #include<cmath> #include ...
- poj 2382 Apple Catching 入门dp
点击打开链接 #include <iostream> #include <algorithm> using namespace std; const int M =1010; ...
- Team Silver_Bullet 训练记录
Team members Vec Grunt henryrabbit To do list team:起队名 每周组队训练 补题 Vec: Grunt:切题,切题,切更多的题!做好切所有类型题的觉悟! ...
最新文章
- leetcode第二题java_LeetCode第二题,Java实现
- java编写数字金字塔_用JAVA写数字金字塔
- Ocelot中文文档-缓存
- jstl sql标签使用
- STL 中的 accumulate(C++)
- 【kafka】已解决 kafka No current assignment for partition
- 小程序入门学习04--数据绑定、条件渲染、列表渲染
- Weblogic常用监控指标
- python 进化树_Biopython之系统发育树(进化树)的绘制
- [教程]安装系统解码器 - 指导教程
- AST使用eval运行函数,更换数值
- 互动派年会-comsol专题超强干货剖析
- 2015年微信营销趋势分析与归纳!
- Linux下Docker安装微信文件传输问题
- 瓜瓜的时空旅行,第三次模拟赛,dfs序+线段树维护最小值
- EasyPoi 实现Word文档内容替换3种情况(正常文本替换、表格文本替换、图表替换)
- 去哪儿网2015春季校招笔试--回忆版
- 下载refseq序列
- 模仿淘宝web扫码登录
- nyistOJ-See LCS again(二分)