POJ 3683 Priest John's Busiest Day【2-sat】

题意:有 n 对新人结婚,只有一个牧师,知道了每个婚礼的开始时间 s,和结束时间 t 和需要牧师的主持时间 las,牧师可以选在在[s,s+las]或[t-las,t]两个时间段内主持,

        问是否存在一个时间安排,使得所有新人都可以得到牧师的主持。 

分析: 每一个婚礼主持时间都是两种状态,每个婚礼之间的时间可能会互相限制,可以用2-sat判断是否冲突。

       建图:

       每个婚礼的两个时间段 i = [s,s+las],i +n = [t-las,t]

       如果 i       和 j       冲突,建边 i        ->   j + n

       如果 i       和 j + n 冲突,建边 i        ->   j

       如果 i + n  和 j       冲突,建边 i + n  ->   j + n

       如果 i + n  和 j + n 冲突,建边 i + n  ->   j

       求出强连通分量并染色,判断是否有 i 和 i+n在一个集合的情况,如果有则不存在

       否则反向拓扑排序,找出一组解即可。

#include<stdio.h>
#include<string.h>
#define min(a,b)(a)<(b)?(a):(b)
#define max(a,b)(a)>(b)?(a):(b)
#define clr(x)memset(x,0,sizeof(x))
#define maxn 2100
#define maxm 3000000
struct node
{
    int from,to,next;
}e[maxm],sed[maxm];
int head[maxn];
int sorh[maxn];
int tot;
int tt;
void add(int s,int t)
{
    e[tot].from=s;
    e[tot].to=t;
    e[tot].next=head[s];
    head[s]=tot++;
}
void add2(int s,int t)
{
    sed[tt].to=t;
    sed[tt].next=sorh[s];
    sorh[s]=tt++;
}
int ti,sn,top,n;
int low[maxn];
int dfn[maxn];
int ins[maxn];
int sta[maxn];
int col[maxn];
int sco[maxn];
int ct[maxn];
int q[maxn];
int ind[maxn];
int res[maxn];
void tarjan(int u)
{
    dfn[u]=low[u]=++ti;
    ins[u]=1;
    sta[++top]=u;
    int i,k;
    for(i=head[u];i;i=e[i].next)
    {
        k=e[i].to;
        if(dfn[k]==0)
        {
            tarjan(k);
            low[u]=min(low[u],low[k]);
        }
        else if(ins[k])
            low[u]=min(low[u],dfn[k]);
    }
    if(dfn[u]==low[u])
    {
        sn++;
        do
        {
            k=sta[top--];
            ins[k]=0;
            sco[k]=sn;
        }while(k!=u);
    }
}
struct edge
{
    int s1,e1,s2,e2;
}p[maxn];
char st[22],en[22];
int main()
{
    scanf("%d",&n);
    int i,j,k,las,front,rear;
    for(i=0;i<n;i++)
    {
        scanf("%s%s%d",st,en,&las);
        p[i].s1=((st[0]-'0')*10+st[1]-'0')*60+(st[3]-'0')*10+st[4]-'0';
        p[i].e1=p[i].s1+las;
        p[i].e2=((en[0]-'0')*10+en[1]-'0')*60+(en[3]-'0')*10+en[4]-'0';
        p[i].s2=p[i].e2-las;
    }
    clr(head);
    tot=1;
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
        {
            if(i==j)
                continue;
            if(p[i].s1<p[j].e1&&p[j].s1<p[i].e1)
                add(i,j+n);
            if(p[i].s1<p[j].e2&&p[j].s2<p[i].e1)
                add(i,j);
            if(p[i].s2<p[j].e1&&p[j].s1<p[i].e2)
                add(i+n,j+n);
            if(p[i].s2<p[j].e2&&p[j].s2<p[i].e2)
                add(i+n,j);
        }
        ti=sn=top=0;
        clr(sco); clr(dfn);  
        clr(low); clr(ins);
        for(i=0;i<2*n;i++)
            if(!dfn[i])
                tarjan(i);
        int flag=0;
        for(i=0;i<n;i++)
        {
            if(sco[i]==sco[i+n])
            flag=1;
            ct[sco[i]]=sco[i+n];
            ct[sco[i+n]]=sco[i];
        }
        if(flag)
            goto loop;
        tt=1;
        clr(sorh);
        clr(ind); 
        clr(col);
        for(i=1;i<tot;i++)
            if(sco[e[i].from]!=sco[e[i].to])
            {
                add2(sco[e[i].to],sco[e[i].from]);
                ind[sco[e[i].from]]++;
            }
        front=0,rear=0;
        for(i=1;i<=sn;i++)
            if(ind[i]==0)
                q[rear++]=i;
        while(front<rear)
        {
            int x=q[front++];
            if(col[x]==0)
            {
                col[x]=1;
                col[ct[x]]=-1;
            }
            for(i=sorh[x];i;i=sed[i].next)
            {
                k=sed[i].to;
                if(--ind[k]==0)
                    q[rear++]=k;
            }
        }
        clr(res);
        for(i=0;i<2*n;i++)
            if(col[sco[i]]==1)
                res[i]=1;
loop:   if(flag)
            printf("NO\n");
        else
        {
            printf("YES\n");
            for(i=0;i<n;i++)
            {
                if(res[i])
                    printf("%02d:%02d %02d:%02d\n",p[i].s1/60,p[i].s1%60,p[i].e1/60,p[i].e1%60);
                else 
                    printf("%02d:%02d %02d:%02d\n",p[i].s2/60,p[i].s2%60,p[i].e2/60,p[i].e2%60);
            }
        }
    return 0;
}

 

posted @ 2012-10-01 10:40  'wind  阅读(201)  评论(0编辑  收藏  举报