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 //就这样吧
posted on 2014-10-29 15:43 Pentium.Labs 阅读(195) 评论(0) 编辑 收藏 举报