Priest John's Busiest Day (2-sat)

题面
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 Si + Di, 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.
题意
挑战P326
思路
记\(x_i\)为第\(i\)对新人在开始时举行仪式
记\(\overline{x_i}\)为第\(i\)对新人在结束时举行仪式

如果\(x_i\)与\(x_j\)冲突,那么\(x_i\)与\(x_j\)不能同时取到,所以连边\(x_i\)->\(\overline{x_j}\),\(x_j\)->\(\overline{x_i}\)

其他三种情况同理

注意,结束时间可以和另外一个开始时间相同

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>

#define fuck(x) cerr<<#x<<" = "<<x<<endl;
#define debug(a, x) cerr<<#a<<"["<<x<<"] = "<<a[x]<<endl;
#define lson l,mid,ls
#define rson mid+1,r,rs
#define ls (rt<<1)
#define rs ((rt<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int loveisblue = 486;
const int maxn = 1000086;
const int maxm = 2000086;
const int inf = 0x3f3f3f3f;
const ll Inf = 999999999999999999;
const int mod = 1000000007;
const double eps = 1e-6;
const double pi = acos(-1);


int n;
int point1(int x){
    return x;
}
int point2(int x){
    return x+n;
}

char s[10];
struct node{
    int st,ed,d;
}a[maxn];

int cal(){
    int tmp1 = (s[0]-48)*10 + s[1]-48;
    int tmp2 = (s[3]-48)*10 + s[4]-48;
    return tmp1*60 + tmp2;
}

int check(int st1,int st2,int d1,int d2){
    int ed1 = st1+d1;
    int ed2 = st2+d2;
    if(ed1>st2&&ed1<=ed2){
        return true;
    }else return ed2 > st1 && ed2 <= ed1;
}

int Head[maxn],cnt;
struct edge{
    int Next,v;
}e[maxm],et[maxm];
void add_edge(int u,int v){
//    cerr<<u<<" "<<v<<endl;
    e[cnt].Next=Head[u];
    e[cnt].v=v;
    Head[u]=cnt++;
}

int Headt[maxn],cntt;
void add_edget(int u,int v){
//    cerr<<u<<" "<<v<<endl;
    et[cntt].Next=Headt[u];
    et[cntt].v=v;
    Headt[u]=cntt++;
}

int dfn[maxn],low[maxn],color[maxn];
int Index,sig;//只有这两个变量和dfn需要初始化
bool vis[maxn];
stack<int>sta;
void Tarjan(int u)
{
    dfn[u]=low[u]=++Index;
    sta.push(u);
    vis[u]=true;

    for(int k=Head[u];k!=-1;k=e[k].Next){
        int v = e[k].v;
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(vis[v]){low[u]=min(low[u],low[v]);}
    }

    if(dfn[u]==low[u]){
        sig++;
        while(true){
            int cur=sta.top();
            sta.pop();
            color[cur]=sig;
            vis[cur]=false;
            if(cur==u){break;}
        }
    }
}


queue<int>q;
int du[maxn];
int num[maxn];
void top_sort(){
    int cur = 0;
    while (!q.empty()){
        int tmp = q.front();
//        fuck(tmp)
        q.pop();
        num[tmp]=++cur;
        for(int k=Headt[tmp];~k;k=et[k].Next){
//            fuck(k)
            du[et[k].v]--;
            if(du[et[k].v]==0){
                q.push(et[k].v);
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(true);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    memset(Head,-1,sizeof(Head));
    memset(Headt,-1,sizeof(Headt));
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        a[i].st = cal();
        scanf("%s",s);
        a[i].ed = cal();
        scanf("%d",&a[i].d);
        for(int j=1;j<i;j++){
            //开始与开始相冲突
            if(check(a[i].st,a[j].st,a[i].d,a[j].d)){
                add_edge(point1(i),point2(j));
                add_edge(point1(j),point2(i));
            }if(check(a[i].st,a[j].ed-a[j].d,a[i].d,a[j].d)){
                add_edge(point1(i),point1(j));
                add_edge(point2(j),point2(i));
            }if(check(a[i].ed-a[i].d,a[j].st,a[i].d,a[j].d)){
                add_edge(point1(j),point1(i));
                add_edge(point2(i),point2(j));
            }if(check(a[i].ed-a[i].d,a[j].ed-a[j].d,a[i].d,a[j].d)){
                add_edge(point2(i),point1(j));
                add_edge(point2(j),point1(i));
            }
        }
    }

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

    bool flag=true;
    for(int i=1;i<=n;i++){
        if(color[point1(i)]==color[point2(i)]){
            flag=false;
        }
    }
    if(flag){
        printf("YES\n");
        for(int i=1;i<=2*n;i++){
            for(int k=Head[i];~k;k=e[k].Next){
                if(color[i]!=color[e[k].v]){
                    add_edget(color[i],color[e[k].v]);
                    du[color[e[k].v]]++;
                }
            }
        }
        for(int i=1;i<=sig;i++){
            if(du[i]==0){
                q.push(i);
            }
        }
        top_sort();
        for(int i=1;i<=n;i++){
            if(num[color[point1(i)]]>num[color[point2(i)]]){
                printf("%02d:%02d ",a[i].st/60,a[i].st%60);
                a[i].st+=a[i].d;
                printf("%02d:%02d\n",a[i].st/60,a[i].st%60);
            }else{
                a[i].ed-=a[i].d;
                printf("%02d:%02d ",a[i].ed/60,a[i].ed%60);
                a[i].ed+=a[i].d;
                printf("%02d:%02d\n",a[i].ed/60,a[i].ed%60);
            }
        }
    }else{
        printf("NO\n");
    }
    return 0;
}
上一篇:【Python笔记】Python变量类型


下一篇:Swift从入门到精通第十三篇 - 可选项响应链 初识