首页 > 代码库 > poj 3683 2-SAT入门
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 for( int ii = 1; ii <= scc_cnt; ii++ )183 {184 int i = done[ii];185 if( color[i] != 0 ) continue;186 color[i] = 1;187 dfs( cfl[i] );188 }189 printf("YES\n");190 for( int i = 1; i <= N; i++ )191 if( color[ sccno[i] ] == 1 )192 print( S[i], S[i]+D[i] );193 else194 print( T[i]-D[i], T[i] );195 196 return 0;197 }198 199 200 //一直觉得ICPC不应该是种功利性的东西,那样就彻底变味了,也没意义了201 //今年要干就好好干吧,也许明年就不打了202 //没办法,有些事太复杂203 //反正个人认为几个真心的朋友比所谓的成绩重要得多得多。204 //。205 //就这样吧
poj 3683 2-SAT入门
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。