POJ 3683 Priest John's Busiest Day[2-SAT 构造解]

题意:

$n$对$couple$举行仪式,有两个时间段可以选择,问是否可以不冲突举行完,并求方案


 

两个时间段选择对应一真一假,对于有时间段冲突冲突的两人按照$2-SAT$的规则连边(把不冲突的时间段连起来)

然后本题需要构造解,所以要$SCC$缩点反向建图记录否定再拓扑排序$dfs$染色,好麻烦...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2005,M=1e6+5;
typedef long long ll;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int n,m;
struct person{
    int a,b;
}p[N];
struct edge{
    int v,ne;
}e[M],e2[M];
int h[N],h2[N],cnt=0;
inline void ins(int u,int v){
    cnt++;
    e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
}
inline void ins2(int u,int v){
    cnt++;
    e2[cnt].v=v;e2[cnt].ne=h2[u];h2[u]=cnt;
}
inline bool isIn(int x,int y){
    if(p[x].b<=p[y].a||p[x].a>=p[y].b) return false;
    return true;
}
void buildGraph(){
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
            int x=i<<1,y=j<<1;
            if(isIn(x-1,y-1)) ins(x-1,y),ins(y-1,x);
            if(isIn(x-1,y)) ins(x-1,y-1),ins(y,x);
            if(isIn(x,y-1)) ins(x,y),ins(y-1,x-1);
            if(isIn(x,y)) ins(x,y-1),ins(y,x-1);
        }
}
int dfn[N],low[N],dfc,belong[N],scc;
int st[N],top;
void dfs(int u){
    dfn[u]=low[u]=++dfc;
    st[++top]=u;
    for(int i=h[u];i;i=e[i].ne){
        int v=e[i].v;
        if(!dfn[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);
        }else if(!belong[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        scc++;
        while(true){
            int x=st[top--];
            belong[x]=scc;
            if(x==u) break;
        }
    }
}
bool judge(){
    for(int i=1;i<=n;i++) if(belong[i<<1]==belong[(i<<1)-1]) return false;
    return true;
}
int ind[N];
void rebuildGraph(){
    int _=n<<1;
    cnt=0;
    for(int u=1;u<=_;u++)
        for(int i=h[u];i;i=e[i].ne) 
            if(belong[u]!=belong[e[i].v]) 
                ins2(belong[e[i].v],belong[u]),ind[belong[u]]++;
}
int color[N];
void dfsCol(int u){
    if(color[u]) return;
    color[u]=2;
    for(int i=h2[u];i;i=e2[i].ne) dfsCol(e2[i].v);
}
int opp[N];
void topoSort(){
    top=0;
    for(int i=1;i<=scc;i++) if(!ind[i]) st[++top]=i;
    while(top){
        int u=st[top--];
        if(color[u]) continue;
        color[u]=1;dfsCol(opp[u]);
        for(int i=h2[u];i;i=e2[i].ne){
            int v=e2[i].v;
            ind[v]--;
            if(!ind[v]) st[++top]=v;
        }
    }
}
void print(int a,int b){
    printf("%.2d:%.2d ",a/60,a%60);
    printf("%.2d:%.2d ",b/60,b%60);
    puts("");
}
int main(){
    freopen("in","r",stdin);
    n=read();
    for(int i=1;i<=n;i++){
        int x=i<<1,t;
        t=read();
        p[x-1].a=t*60+read();
        t=read();
        p[x].b=t*60+read();
        t=read();
        p[x-1].b=p[x-1].a+t;
        p[x].a=p[x].b-t;
    }
    buildGraph();
    int _=n<<1;
    for(int i=1;i<=_;i++) if(!dfn[i]) dfs(i);
    if(!judge()) puts("NO");
    else{
        puts("YES");
        rebuildGraph();
        for(int i=1;i<=n;i++){
            int x=i<<1;
            opp[belong[x]]=belong[x-1];
            opp[belong[x-1]]=belong[x];
        }
        topoSort();
        for(int i=1;i<=n;i++){
            int x=i<<1;
            if(color[belong[x]]==1) print(p[x].a,p[x].b);
            else print(p[x-1].a,p[x-1].b);
        }
    }
}

 

posted @ 2017-02-21 23:57  Candy?  阅读(247)  评论(0编辑  收藏  举报