POJ 3683 Priest John's Busiest Day

2-SAT简单题,判断一下两个开区间是否相交

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;

const int maxn=2000+10;
int N,M;
struct Time
{
    int Start;
    int End;
    int cost;
    int S1,E1,S2,E2;
} t[maxn];
char s[1000];

struct TwoSAT
{
    int n;
    vector<int> G[maxn*2];
    bool mark[maxn*2];
    int S[maxn*2],c;

    bool dfs(int x)
    {
        if(mark[x^1]) return false;
        if(mark[x]) return true;
        mark[x]=true;
        S[c++]=x;
        for(int i=0;i<G[x].size();i++)
            if(!dfs(G[x][i])) return false;
        return true;
    }

    void init(int n)
    {
        this->n=n;
        for(int i=0;i<n*2;i++) G[i].clear();
        memset(mark,0,sizeof mark);
    }

    void add_clause(int x,int y)
    {
        G[x].push_back(y^1);
        G[y].push_back(x^1);
    }

    bool solve()
    {
        for(int i=0;i<2*n;i+=2)
            if(!mark[i]&&!mark[i+1])
            {
                c=0;
                if(!dfs(i))
                {
                    while(c>0) mark[S[--c]]=false;
                    if(!dfs(i+1)) return false;
                }
            }
        return true;
    }
};

bool F(int x1,int y1,int x2,int y2)
{
    if(x1<x2&&x2<y1) return 1;//区间相交
    if(x1<y2&&y2<y1) return 1;//区间相交
    if(x2<x1&&x1<y2) return 1;//区间相交
    if(x2<y1&&y1<y2) return 1;//区间相交
    if(x1==x2||y1==y2) return 1;//区间相交
    return 0;//区间不相交
}

int main()
{
    while(~scanf("%d",&N))
    {
        TwoSAT T; T.n=N; T.init(N);
        for(int i=0; i<N; i++)
        {
            int h1,h2,m1,m2,tt;
            
            scanf("%s",s);
            h1=(s[0]-'0')*10+(s[1]-'0');
            m1=(s[3]-'0')*10+(s[4]-'0');

            scanf("%s",s);
            h2=(s[0]-'0')*10+(s[1]-'0');
            m2=(s[3]-'0')*10+(s[4]-'0');

            scanf("%d",&tt);

            t[i].Start=h1*60+m1;
            t[i].End=h2*60+m2;
            t[i].cost=tt;
            
            t[i].S1=t[i].Start;
            t[i].E1=t[i].Start+t[i].cost;
            
            t[i].S2=t[i].End-t[i].cost;
            t[i].E2=t[i].End;
        }
        
        for(int i=0;i<N;i++)
        {
            for(int j=i+1;j<N;j++)
            {
                if(F(t[i].S1,t[i].E1,t[j].S1,t[j].E1)) 
                    T.add_clause(2*i,2*j);
                if(F(t[i].S1,t[i].E1,t[j].S2,t[j].E2)) 
                    T.add_clause(2*i,2*j+1);    
                if(F(t[i].S2,t[i].E2,t[j].S1,t[j].E1)) 
                    T.add_clause(2*i+1,2*j);
                if(F(t[i].S2,t[i].E2,t[j].S2,t[j].E2)) 
                    T.add_clause(2*i+1,2*j+1);
            }
        }
        if(T.solve()) 
        {
            printf("YES
");
            for(int i=0;i<N;i++)
            {
                if(T.mark[2*i]) printf("%02d:%02d %02d:%02d
",t[i].S1/60,t[i].S1%60,t[i].E1/60,t[i].E1%60);
                else  printf("%02d:%02d %02d:%02d
",t[i].S2/60,t[i].S2%60,t[i].E2/60,t[i].E2%60);
            }
        }
        else printf("NO
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/4916749.html