• Priest John's Busiest Day(POJ 3683)


    • 原题如下:
      Priest John's Busiest Day
      Time Limit: 2000MS   Memory Limit: 65536K
      Total Submissions: 12162   Accepted: 4138   Special Judge

      Description

      John is the only priest in his town. September 1st is the John's busiest day in a year because there is an old legend in the town that the couple who get married on that day will be forever blessed by the God of Love. This year N couples plan to get married on the blessed day. The i-th couple plan to hold their wedding from time Si to time Ti. According to the traditions in the town, there must be a special ceremony on which the couple stand before the priest and accept blessings. The i-th couple need Di minutes to finish this ceremony. Moreover, this ceremony must be either at the beginning or the ending of the wedding (i.e. it must be either from Si to SiDi, or from Ti - Di to Ti). Could you tell John how to arrange his schedule so that he can present at every special ceremonies of the weddings.

      Note that John can not be present at two weddings simultaneously.

      Input

      The first line contains a integer N ( 1 ≤ N ≤ 1000). 
      The next N lines contain the SiTi and DiSi and Ti are in the format of hh:mm.

      Output

      The first line of output contains "YES" or "NO" indicating whether John can be present at every special ceremony. If it is "YES", output another N lines describing the staring time and finishing time of all the ceremonies.

      Sample Input

      2
      08:00 09:00 30
      08:15 09:00 20
      
      

      Sample Output

      YES
      08:00 08:30
      08:40 09:00
    • 题解:定义变量xi用于表示对于结婚仪式i在开始还是结束时进行特别仪式:xi为真↔在开始时进行特别仪式
      这样,对于结婚仪式i和j,如果Si~Si+Di和Sj~Sj+Dj冲突,就有¬xi∨¬xj为真。对于开始和结束、结束和开始、结束和结束三种情况,也可以得到类似的条件。于是,要保证所有特别仪式的时间不冲突,只要考虑将所有的子句用∧连接起来所得到的布尔公式就好了。对于输入样例,可以得到布尔公式(¬x1∨¬x2)∧(x1∨¬x2)∧(x1∨x2),当x1为真而x2为假时,其值为真。这样原问题就转为了2-SAT问题。
      注:判断两个区间[s1, e1]、[s2, e2]是否相交:若max(s1, s2)<min(e1, e2)为真,则两区间相交。
    • 代码:
        1 #include <cstdio>
        2 #include <algorithm>
        3 #include <vector>
        4 #include <stack>
        5 #include <cstring>
        6 
        7 using namespace std;
        8 
        9 const int MAX_N=1100;
       10 int N, V;
       11 int S[MAX_N], T[MAX_N], D[MAX_N];
       12 vector<int> G[MAX_N*2];
       13 stack<int> s;
       14 int dfn[MAX_N*2], low[MAX_N*2];
       15 int index;
       16 int cmp[MAX_N*2];
       17 bool instack[MAX_N*2];
       18 int componentnumber;
       19 
       20 void add_edge(int x, int y)
       21 {
       22     G[x].push_back(y);
       23 }
       24 
       25 void tarjan(int i)
       26 {
       27     dfn[i]=low[i]=index++;
       28     instack[i]=true;
       29     s.push(i);
       30     int j;
       31     for (int e=0; e<G[i].size(); e++)
       32     {
       33         j=G[i][e];
       34         if (dfn[j]==-1)
       35         {
       36             tarjan(j);
       37             low[i]=min(low[i], low[j]);
       38         }
       39         else
       40             if (instack[j]) low[i]=min(low[i], dfn[j]);
       41     }
       42     if (dfn[i]==low[i])
       43     {
       44         componentnumber++;
       45         do
       46         {
       47             j=s.top();
       48             s.pop();
       49             instack[j]=false;
       50             cmp[j]=componentnumber;
       51         }
       52         while (j!=i);
       53     }
       54 }
       55 
       56 int main()
       57 {
       58     memset(dfn, -1, sizeof(dfn));
       59     scanf("%d", &N);
       60     for (int i=0; i<N; i++)
       61     {
       62         int a, b, c, d;
       63         scanf("%d:%d %d:%d %d", &a, &b, &c, &d, &D[i]);
       64         S[i]=a*60+b;
       65         T[i]=c*60+d;
       66     }
       67     V=N*2;
       68     for (int i=0; i<N; i++)
       69     {
       70         for (int j=0; j<i; j++)
       71         {
       72             if (min(S[i]+D[i], S[j]+D[j])>max(S[i], S[j]))
       73             {
       74                 add_edge(i, N+j);
       75                 add_edge(j, N+i);
       76             }
       77             if (min(S[i]+D[i], T[j])>max(S[i], T[j]-D[j]))
       78             {
       79                 add_edge(i, j);
       80                 add_edge(N+j, N+i);
       81             }
       82             if (min(T[i], S[j]+D[j])>max(T[i]-D[i], S[j]))
       83             {
       84                 add_edge(N+i, N+j);
       85                 add_edge(j, i);
       86             }
       87             if (min(T[i], T[j])>max(T[i]-D[i], T[j]-D[j]))
       88             {
       89                 add_edge(N+i, j);
       90                 add_edge(N+j, i);
       91             }
       92         }
       93     }
       94     for (int i=0; i<V; i++)
       95     {
       96         if (dfn[i]==-1) tarjan(i);
       97     }
       98     for (int i=0; i<N; i++)
       99     {
      100         if (cmp[i]==cmp[N+i])
      101         {
      102             printf("NO
      ");
      103             return 0;
      104         }
      105     }
      106     printf("YES
      ");
      107     for (int i=0; i<N; i++)
      108     {
      109         if (cmp[i]<=cmp[N+i])
      110         {
      111             printf("%02d:%02d %02d:%02d
      ", S[i]/60, S[i]%60, (S[i]+D[i])/60, (S[i]+D[i])%60);
      112         }
      113         else
      114         {
      115             printf("%02d:%02d %02d:%02d
      ", (T[i]-D[i])/60, (T[i]-D[i])%60, T[i]/60, T[i]%60);
      116         }
      117     }
      118 }
  • 相关阅读:
    产品设计理应遵循哪些原则?
    产品经理必读的九步法
    exec
    Class convert
    Connecting method
    ASP.NET读写操作
    Encrypt Decrypt
    EventHandler, EventArgs
    Convert using code
    Dictionary List
  • 原文地址:https://www.cnblogs.com/Ymir-TaoMee/p/9792129.html
Copyright © 2020-2023  润新知