poj3683

2-SAT算法流程

1.建立选择边

2.tarjan缩点(同一块内必然同时选择),判断是否存在可行解(若存在一对对立点{2*i,2*i-1}在同一块内,则不可行)

3.把缩点后的块之间建立反向选择边,并传递不选择命令(code中用op[ ]数组记录)

4.按照拓扑序找到一为选择的点(块),标为选择,传递不选择标记

//poj3683
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#define inf 2000000000
#define ll long long 
#define mod 1000000007
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,cnt,top,scc,ind;
int a[2005],b[2005],belong[2005],op[2005];
int dfn[2005],low[2005],q[2005];
bool inq[2005];
struct edge{int to,next;}e[2000005],ed[2000005];
int last[2005],last2[2005],d[2005];
int color[2005];
bool jud(int x,int y){
    if(b[x]<=a[y]||a[x]>=b[y])return 0;
    return 1;
}
void insert(int u,int v){e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;}
void insert2(int u,int v){d[v]++;ed[++cnt].to=v;ed[cnt].next=last2[u];last2[u]=cnt;}
void build(){
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
            if(jud(2*i,2*j)){insert(2*i,2*j-1);insert(2*j,2*i-1);}
            if(jud(2*i,2*j-1)){insert(2*i,2*j);insert(2*j-1,2*i-1);}
            if(jud(2*i-1,2*j)){insert(2*i-1,2*j-1);insert(2*j,2*i);}
            if(jud(2*i-1,2*j-1)){insert(2*i-1,2*j);insert(2*j-1,2*i);}
        }
}
void tarjan(int x){
    dfn[x]=low[x]=++ind;
    q[++top]=x;inq[x]=1;
    for(int i=last[x];i;i=e[i].next)
        if(!dfn[e[i].to]){tarjan(e[i].to);low[x]=min(low[e[i].to],low[x]);}
        else if(inq[e[i].to])low[x]=min(dfn[e[i].to],low[x]);
    if(low[x]==dfn[x]){
        int now=0;scc++;
        while(now!=x){
            now=q[top--];
            inq[now]=0;
            belong[now]=scc;
        }
    }
}
void rebuild(){
    cnt=0;
    for(int x=1;x<=2*n;x++)
        for(int i=last[x];i;i=e[i].next)
            if(belong[x]!=belong[e[i].to])
                insert2(belong[e[i].to],belong[x]);
}
void dfs(int x){
    if(color[x])return;
    color[x]=-1;
    for(int i=last2[x];i;i=ed[i].next)dfs(ed[i].to);
}
void topsort(){
    for(int i=1;i<=scc;i++)if(!d[i])q[++top]=i;
    while(top){
        int now=q[top--];
        if(color[now])continue;
        color[now]=1;dfs(op[now]);
        for(int i=last2[now];i;i=ed[i].next){
            d[ed[i].to]--;
            if(!d[ed[i].to])q[++top]=ed[i].to;
        }
    }
}
void print(int x){printf("%.2d:",x/60);printf("%.2d ",x%60);}
int main(){
    n=read();
    int x;
    for(int i=1;i<=n;i++){
        a[2*i]=read();a[2*i]=a[2*i]*60+read();
        b[2*i-1]=read();b[2*i-1]=b[2*i-1]*60+read();
        x=read();b[2*i]=a[2*i]+x;a[2*i-1]=b[2*i-1]-x;
    }
    build();
    for(int i=1;i<=2*n;i++)if(!dfn[i])tarjan(i);
    for(int i=1;i<=n;i++)
        if(belong[2*i]==belong[2*i-1]){puts("NO");return 0;}
    puts("YES");
    rebuild();
    for(int i=1;i<=n;i++){
        op[belong[2*i]]=belong[2*i-1];
        op[belong[2*i-1]]=belong[2*i];
    }
    topsort();
    for(int i=1;i<=n;i++)
        if(color[belong[2*i]]==1)
            print(a[2*i]),print(b[2*i]),puts("");
        else print(a[2*i-1]),print(b[2*i-1]),puts("");
    return 0;
}

 

posted @ 2018-07-03 07:51  lnyzo  阅读(242)  评论(0编辑  收藏  举报