poj 3683 Priest John's Busiest Day 2-sat

经典2-sat问题,需要输出解

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=2e3+9;
int head[4][maxn],lon;
int dfn[maxn],low[maxn],s[maxn],stack[maxn],instack[maxn];
int que[maxn],in[maxn],to[maxn];
int col[maxn];
int top,con,count,totop;
int n,N;
struct
{
    int st,ed,last;
}data[maxn];
struct
{
    int next,to;
}e[maxn*maxn*4];
void edgemake(int from,int to,int head[])
{
    e[++lon].to=to;
    e[lon].next=head[from];
    head[from]=lon;
}
void edgeini()
{
    memset(head,-1,sizeof(head));
    lon=-1;
}
int cal(char d[])
{
    int ret=(d[0]-'0')*600+(d[1]-'0')*60;
    ret+=(d[3]-'0')*10+(d[4]-'0');
    return(ret);
}
void tarjan(int t)
{
    dfn[t]=low[t]=++count;
    stack[++top]=t;
    instack[t]=1;
    for(int k=head[1][t];k!=-1;k=e[k].next)
    {
        int u=e[k].to;
        if(dfn[u]==-1)
        {
            tarjan(u);
            low[t]=min(low[t],low[u]);
        }
        else if(instack[u]==1)
        low[t]=min(low[t],dfn[u]);
    }
    if(dfn[t]==low[t])
    {
        ++con;
        while(1)
        {
            int u=stack[top--];
            instack[u]=0;
            s[u]=con;
            edgemake(con,u,head[2]);
            if(u==t) break;
        }
    }
}
void tarjan()
{
    memset(dfn,-1,sizeof(dfn));
    count=con=top=0;
    for(int i=2;i<=n*2+1;i++)
    if(dfn[i]==-1)
    tarjan(i);
}

bool check(int a,int b,int c,int d)
{
    if(c>=b||a>=d) return false;
    return true;
}

bool check()
{
    for(int i=2;i<=n*2;i+=2)
    if(s[i]==s[i+1])
    return false;
    return true;
}

void makegraph()
{
    for(int i=2;i<=N;i++)
    for(int k=head[1][i];k!=-1;k=e[k].next)
    if(s[i]!=s[e[k].to])
    edgemake(s[e[k].to],s[i],head[3]);
}

void topo()
{
    totop=0;
    int top=0;
    memset(in,0,sizeof(in));
    for(int i=1;i<=con;i++)
    for(int k=head[3][i];k!=-1;k=e[k].next)
    in[e[k].to]++;
    for(int i=1;i<=con;i++)
    if(in[i]==0)
    que[++top]=i;
    while(top)
    {
        int u=que[top--];
        to[++totop]=u;
        for(int k=head[3][u];k!=-1;k=e[k].next)
        {
            int v=e[k].to;
            in[v]--;
            if(in[v]==0)
            que[++top]=v;
        }
    }
}

void paint(int t)
{
    for(int k=head[3][t];k!=-1;k=e[k].next)
    {
        int v=e[k].to;
        if(col[v]==-1)
        {
            col[v]=0;
            paint(v);
        }
    }
}

void colour()
{
    memset(col,-1,sizeof(col));
    for(int i=1;i<=totop;i++)
    {
        int u=to[i];
        if(col[u]==-1)
        {
            col[u]=1;
            for(int k=head[2][u];k!=-1;k=e[k].next)
            {
                int v=e[k].to;
                if(col[s[v^1]]==-1)
                {
                    col[s[v^1]]=0;
                    paint(s[v^1]);
                }
            }
        }
    }
}

void prin(int t)
{
    if(t%2==0)
    {
        printf("%02d:%02d ",data[t/2].st/60,data[t/2].st%60);
        printf("%02d:%02d\n",(data[t/2].st+data[t/2].last)/60,(data[t/2].st+data[t/2].last)%60);
    }
    else
    {
        printf("%02d:%02d ",(data[t/2].ed-data[t/2].last)/60,(data[t/2].ed-data[t/2].last)%60);
        printf("%02d:%02d\n",data[t/2].ed/60,data[t/2].ed%60);
    }
}

void prin()
{
    printf("YES\n");
    for(int i=2;i<=N;i++)
    if(col[s[i]]==1)
    {
        prin(i);
    }
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        N=n+n+1;
        edgeini();
        for(int i=1;i<=n;i++)
        {
            char st[10],ed[10];
            scanf("%s %s %d",st,ed,&data[i].last);
            data[i].st=cal(st);
            data[i].ed=cal(ed);
        }
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(check(data[i].st,data[i].st+data[i].last,data[j].st,data[j].st+data[j].last))
            {
                edgemake(i*2,j*2+1,head[1]);
                edgemake(j*2,i*2+1,head[1]);
            }
            if(check(data[i].st,data[i].st+data[i].last,data[j].ed-data[j].last,data[j].ed))
            {
                edgemake(i*2,j*2,head[1]);
                edgemake(j*2+1,i*2+1,head[1]);
            }
            if(check(data[i].ed-data[i].last,data[i].ed,data[j].st,data[j].st+data[j].last))
            {
                edgemake(i*2+1,j*2+1,head[1]);
                edgemake(j*2,i*2,head[1]);
            }
            if(check(data[i].ed-data[i].last,data[i].ed,data[j].ed-data[j].last,data[j].ed))
            {
                edgemake(i*2+1,j*2,head[1]);
                edgemake(j*2+1,i*2,head[1]);
            }
        }
        tarjan();
        if(!check())
        {
            printf("NO\n");
            continue;
        }
        makegraph();
        topo();
        colour();
        prin();
    }
    return 0;
}


你可能感兴趣的:(poj 3683 Priest John's Busiest Day 2-sat)