Poj P3683 Priest John's Busiest Day___2-SAT

版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/80398222

题目大意:

给出N个个婚礼的描述Ai,Bi,Li
婚礼可以从[Ai,Ai+Li]或[BiLi,Bi]2段时间开始,
问是否存在一种安排方式使得婚礼两两不冲突,如果有,请输出安排方案。

N1000

分析:

可以转化成2-SAT的模型,
对于第i个婚礼的2段可用时间[L1iR1i],[L2iR2i],设为T1iT2i
以及第j个婚礼的2段可用时间[L1jR1j],[L2jR2j],设为T1jT2j
①当T1iT2i冲突
则显然
T1i必只能选T2j
T2i必只能选T1j

②当T1iT2j冲突
则显然
T1i必只能选T2i
T2j必只能选T1j

③当T1jT2i冲突
则显然
T1j必只能选T2j
T2i必只能选T1i

④当T1jT2j冲突
则显然
T1j必只能选T2i
T2j必只能选T1i

然后就这样通过强连通分量判定是否有解
因为要求方案,
可以通过tarjan缩点然后用拓扑排序求

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#define N 2005

using namespace std;

struct node{
      int aa, bb;
}t[N];

struct Node{
       int to, next;
}a[N * N];

vector <int> E[N];

int Instack[N], Belong[N], dfn[N], low[N], Ls[N];
int Color[N], Cp[N], Insum[N];
int n, cnt, tot, num;

void Addedge(int u, int v) {
     tot++;
     a[tot].to = v;
     a[tot].next = Ls[u];
     Ls[u] = tot;
}

bool Check(int x, int y) {
     if (t[x].aa >= t[y].bb || t[y].aa >= t[x].bb) return 0;
     return 1;
}

stack <int> st;  
queue <int> Q;

void Tarjan(int u) { 
     dfn[u] = low[u] = ++num;  
     Instack[u] = 1;  
     st.push(u);  
     for (int i = Ls[u]; i; i = a[i].next) {   
          int v = a[i].to;  
          if (!dfn[v]){  
              Tarjan(v);  
              low[u] = min(low[u], low[v]);  
          }  
          else if (Instack[v]) low[u] = min(low[u], dfn[v]);  
     }   
     if (low[u] == dfn[u]) {  
          cnt++;
          int rp;
          while ("rp++") {
                 rp = st.top(); 
                 st.pop();  
                 Instack[rp] = 0;  
                 Belong[rp] = cnt;  
                 if (rp == u) break;
          } 
     }   
}  

void Top_sort() {
     for (int u = 1; u <= 2 * n; u++) {
             for (int i = Ls[u]; i ; i = a[i].next) {
                  int v = a[i].to;
                  if (Belong[u] != Belong[v]) {
                      E[Belong[v]].push_back(Belong[u]); 
                      Insum[Belong[u]]++;
                  }
             }
       }

       for (int i = 1; i <= cnt; i++)
            if (!Insum[i]) Q.push(i); 

       while (!Q.empty()) {
             int u = Q.front();
             Q.pop();
             if (!Color[u]) {
                      Color[u] = 1;      
                      Color[Cp[u]] = 2;
             }
             for (int v = 0; v < E[u].size(); v++){
                  Insum[E[u][v]]--;
                  if (!Insum[E[u][v]]) Q.push(E[u][v]);
             }
       }
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
         int a, b, c, d, e;
         scanf("%d:%d %d:%d %d", &a, &b, &c, &d, &e);
         t[i].aa = a * 60 + b;
         t[i].bb = t[i].aa + e;
         t[i + n].aa = c * 60 + d - e;
         t[i + n].bb = c * 60 + d;
    }
      for (int i = 1; i <= n; i++)
           for (int j = 1; j <= n; j++) 
                if (i != j) {
                    if (Check(i, j)) Addedge(i, j + n);
                    if (Check(i, j + n)) Addedge(i, j);
                    if (Check(i + n, j)) Addedge(i + n, j + n);
                    if (Check(i + n, j + n)) Addedge(i + n, j);
                }

           for (int i = 1; i <= 2 * n; i++)
                if (!dfn[i]) Tarjan(i);

           for (int i = 1; i <= n; i++) {
                if (Belong[i] == Belong[i + n]){
                    printf("NO\n");
                    return 0;
               }
               Cp[Belong[i]] = Belong[i + n];
               Cp[Belong[i + n]] = Belong[i]; 
          }
          printf("YES\n");

          Top_sort();

          for (int i = 1; i <= n; i++){
               int j = i + n;
               if (Color[Belong[i]] == 1) printf("%.2d:%.2d %.2d:%.2d\n", t[i].aa / 60, t[i].aa % 60,t[i].bb / 60,t[i].bb % 60);
                                     else printf("%.2d:%.2d %.2d:%.2d\n", t[j].aa / 60, t[j].aa % 60,t[j].bb / 60,t[j].bb % 60);
          }
}
阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页