zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ");
    156             return 0;
    157         }
    158     }
    159 
    160     //printf("YES
    ");
    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
    ");
    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 //就这样吧
  • 相关阅读:
    第二周例行报告
    洛谷 P3384 【模板】轻重链剖分
    洛谷 P3380 【模板】二逼平衡树(树套树)
    洛谷 P4568 [JLOI2011]飞行路线
    2018 ICPC Asia Nanjing Regional Preliminary L. Magical Girl Haze
    牛客 2020 牛客国庆集训派对 day8 G. Shuffle Cards
    洛谷 P3224 [HNOI2012]永无乡
    洛谷 P1486 [NOI2004]郁闷的出纳员
    洛谷 P3391 【模板】文艺平衡树
    洛谷 P3369 【模板】普通平衡树
  • 原文地址:https://www.cnblogs.com/pdev/p/4059706.html
Copyright © 2011-2022 走看看