• poj 3683 Priest John's Busiest Day (2sat 模版)


     http://poj.org/problem?id=3683

    题意:

    有n个婚礼,每个婚礼有起始时间si,结束时间ti,还有一个主持时间ti,ti必须安排在婚礼的开始或者结束,

    主持由祭祀来做,但是只有一个祭祀,所以 各个婚礼的主持时间不能重复,问你有没有可能正常的安排主持时间,

    不能输出no,能的话要输出具体的答案:即每个婚礼的主持时间段是什么样的。

    2-sat 问题。建图:

    对于每个婚礼,主持时间只有两种状态,而且各个婚礼之间的主持时间之间有相互限制,自然想到2-sat。

    对于婚礼i和婚礼j。i表示在开始主持,i2表示在结束主持,j类似。

    枚举每一对不同的i和j。

    如果i和j冲突。连接i j2

    如果i和j2冲突,连接i j

    如果i2和j冲突,连接i2 j2

    如果i2和j2冲突,连接i2 j

    然后就是Tarjan求强联通,判断2-sat问题,成立的话,topsort,输出答案。



      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<set>
      7 #include<map>
      8 #include<queue>
      9 #include<vector>
     10 #include<string>
     11 #define Min(a,b) a<b?a:b
     12 #define Max(a,b) a>b?a:b
     13 #define CL(a,num) memset(a,num,sizeof(a));
     14 #define eps  1e-12
     15 #define inf 100000000
     16 #define mx 1<<60
     17 #define ll   __int64
     18 const double pi  = acos(-1.0);
     19 const int maxn = 1200;
     20 using namespace std;
     21 int  top,num,bcnt,belong[maxn*2],instack[maxn*2],stack[maxn*2],dfn[maxn*2],low[maxn*2];
     22 int n ,m;
     23 int opp[maxn * 2],col[maxn * 2],in[maxn*2],head[maxn*2];
     24 int ans[maxn*2] ;
     25 struct pnode
     26 {
     27     int from ;
     28     int to;
     29     int next;
     30 }p[maxn*maxn],eg[maxn*maxn];
     31 
     32 int cnt ,next[maxn*2];
     33 void add(int u,int v)
     34 {
     35     p[cnt].from = u;
     36     p[cnt].to = v;
     37     p[cnt].next  = next[u];
     38     next[u] = cnt++;
     39 
     40 }
     41 
     42 void tarjan(int i)//tarjan  求强联通 分量
     43 {
     44     int j,k;
     45     dfn[i] = low[i] = ++num;
     46     stack[++top] = i;
     47     instack[i] = 1;
     48     for(k = next[i] ; k != -1;k = p[k].next)
     49     {
     50 
     51          j = p[k].to ;
     52         if(!dfn[j])
     53         {
     54             tarjan(j);
     55             if(low[j] < low[i]) low[i] = low[j] ;
     56         }
     57         else
     58         {
     59             if(instack[j] && dfn[j] < low[i]) low[i] = dfn[j] ;
     60         }
     61 
     62     }
     63     if(dfn[i] == low[i])
     64     {
     65         bcnt++;
     66         do
     67         {
     68             j = stack[top--];
     69             instack[j] = 0 ;
     70             belong[j] = bcnt ;
     71         }while(j != i);
     72     }
     73 }
     74 void insert(int u,int v)
     75 {
     76     eg[num].from = u;
     77     eg[num].to = v;
     78     eg[num].next = head[u];
     79     head[u] = num++;
     80 }
     81 bool  solve()//tarjan  + topsort染色输出
     82 {
     83     int i, l;
     84     for(i =0 ; i <= n*2;i++)
     85     {
     86         dfn[i] = low[i] = instack[i] = stack[i] = belong[i] = 0;
     87     }
     88     top = bcnt = num = 0;
     89     for(i = 0 ; i < n*2;i++)
     90     {
     91         if(!dfn[i])tarjan(i);
     92     }
     93     for(i =0 ;i< n;i++)
     94     {
     95         if(belong[i] == belong[i + n]) return false ;//判断是否 有解
     96 
     97         opp[belong[i]] = belong[i + n];//记录 对立 点的位置 
     98         opp[belong[i+n]] = belong[i] ;
     99     }
    100    //下面重新构图
    101     CL(col,0);
    102     CL(in,0);
    103     CL(head,-1);
    104     num = 0;
    105      for(i = 0 ; i < cnt ;i++)
    106      {
    107          if(belong[p[i].from] != belong[p[i].to])
    108          {
    109              insert(belong[p[i].to],belong[p[i].from]);//  (将 缩点 )反向建图 
    110              in[belong[p[i].from]]++;//记录每个点的入度
    111          }
    112      }
    113      queue<int>que;
    114      for(i = 0 ;i < bcnt;i++)//将入度为0 的点 入队列
    115      {
    116          if(in[i] == 0) {que.push(i);}
    117      }
    118      while(!que.empty())
    119      {
    120          int k = que.front();que.pop();
    121 
    122          if(col[k] == 0)
    123          {
    124              col[k] = 1;//染为 红色 
    125              col[opp[k]] = -1;//  将 对立点染为 绿色
    126 
    127 
    128          }
    129           for(i = head[k];i!=-1;i = eg[i].next)
    130              {
    131                 int v = eg[i].to;
    132                 in[v]--;
    133                 if(in[v] == 0)que.push(v) ;
    134 
    135              }
    136 
    137 
    138      }
    139       CL(ans,0);
    140      for(i = 0 ; i < 2*n;i++)
    141      {
    142          if(col[belong[i]] == 1)//标记 染为 红色的 点  ,
    143          {
    144              ans[i] = 1;
    145          }
    146      }
    147 
    148    return  true;
    149 
    150 
    151 }
    152 void init()
    153 {
    154     CL(next,-1);
    155     cnt = 0 ;
    156 
    157 }
    158 struct node
    159 {
    160     int  from;
    161     int   to;
    162     int len ;
    163 }q[maxn] ;
    164 int judge( char *c)
    165 {
    166     int a,b;
    167     sscanf(c,"%d:%d",&a,&b);
    168 
    169     return a*60 + b ;
    170 
    171 
    172 }
    173 int judge1(int a,int b,int c,int d)
    174 {
    175 
    176    if(b <= c || d <= a) return 0;
    177 
    178     return 1;
    179 }
    180 void pf(int x)
    181 {
    182     printf("%02d:%02d",x/60,x%60) ;
    183 }
    184 int main()
    185 {
    186     int i,j,a,b,c;
    187 
    188     //freopen("data.txt","r",stdin) ;
    189     char str1[10],str2[10];
    190      while(scanf("%d",&n)!=EOF)
    191      {
    192          init() ;
    193         for(i = 0;i < n;i++)
    194         {
    195             scanf("%s %s %d",str1,str2,&q[i].len);
    196 
    197             q[i].from = judge(str1);
    198 
    199             q[i].to = judge(str2);
    200 
    201 
    202 
    203 
    204         }
    205 
    206         for(i = 0 ;i < n;i++)
    207         {
    208             for(j =  0;j < n;j++)
    209             {
    210                     if(i == j)continue ;
    211                 if(judge1(q[i].from,q[i].from + q[i].len,q[j].from,q[j].from + q[j].len))
    212                 {
    213                         add(i,j+n);
    214 
    215 
    216 
    217                 }
    218                  if(judge1(q[i].from,q[i].from + q[i].len,q[j].to - q[j].len,q[j].to ))
    219                 {
    220                         add(i,j);
    221 
    222 
    223 
    224                 }
    225                  if(judge1(q[i].to - q[i].len,q[i].to,q[j].from,q[j].from + q[j].len))
    226                 {
    227                         add(i + n,j+n);
    228 
    229 
    230 
    231                 }
    232                  if(judge1(q[i].to - q[i].len,q[i].to,q[j].to - q[j].len,q[j].to ))
    233                 {
    234                         add(i + n,j);
    235 
    236 
    237 
    238                 }
    239             }
    240         }
    241 
    242         bool  f = solve();
    243         if(f)
    244         {
    245             puts("YES");
    246              for(i =0 ; i< n;i++)
    247              {
    248                  if(ans[i])
    249                  {
    250                      pf(q[i].from);printf(" ");
    251                      pf(q[i].from + q[i].len);
    252                      puts("");
    253                  }
    254                  else
    255                  {
    256                       pf(q[i].to - q[i].len);printf(" ");
    257                       pf(q[i].to);
    258                       puts("");
    259                  }
    260              }
    261         }
    262         else puts("NO");
    263 
    264      }
    265 }
  • 相关阅读:
    final有什么用?
    数组的定义
    作业
    List 、Set数据结构
    报表工具实现单据套打
    动态格报表的制作
    图形钻取
    报表工具轻松搞定卡片式报表
    列表钻取
    报表中如何实现不规则布局
  • 原文地址:https://www.cnblogs.com/acSzz/p/2672465.html
Copyright © 2020-2023  润新知