POJ 3683 2-SAT +输出方案

来源:互联网 发布:及时雨淘宝客 编辑:程序博客网 时间:2024/04/28 13:17

输出方案好烦啊 代码超级多~第一次写这种代码,照着别人的代码打的。。

 

建图:

对于婚礼i和婚礼j,i表示开始主持,i`表示结束主持,j也是一样

枚举每一对不同的i和j,

如果i和j冲突,连接ij`

如果i和j`冲突,连接ij

如果i`和j冲突,连接i`j`

如果i`和j冲突,连接i`j

 

输出方案:

我们可以把处在同一个强连通分量中的点和边缩成一个点,得到新的有向图G1。然后,我们把G中的所有弧反向,得到图G2。
我们把G中所有顶点置为“未着色”。按照拓扑顺序重复下面的操作:
1、选择第一个未着色的顶点x。把x染成红色。
2、把所有与x矛盾的顶点(如果存在bi,~bi∈B ,且bi属于x代表的强连通分量,~bi属于代表y的强连通分量,那么x和y就是互相矛盾的顶点)及其子孙全部全部染成蓝色。
3、重复操作1和2,直到不存在未着色的点为止。此时,G2中被染成红色的点在图G中对应的顶点集合,就对应着该2-SAT的一组解。
此实现可以递归。

#include<stdio.h>#include<string.h>#include<math.h>#include<stack>#define maxn 2010#define maxe  maxn*maxn*3using namespace std;struct node{    int v,next;}edge[maxe];int n;int s[maxn],t[maxn],seq[maxn];int cnt,head1[maxn],head2[maxn],head3[maxn];int scc,idex,dfn[maxn],low[maxn],belong[maxn];int top,sstack[maxn];bool instack[maxn],vis[maxn];int d[maxn],col[maxn];void addedge(int u,int v,int *head){    edge[cnt].v=v;    edge[cnt].next=head[u];    head[u]=cnt++;}void tarjan(int u){    dfn[u]=low[u]=++idex;    sstack[++top]=u;    instack[u]=1;    for(int i=head1[u];i!=-1;i=edge[i].next)    {        int v=edge[i].v;        if(dfn[v]==0)        {            tarjan(v);            low[u]=min(low[v],low[u]);        }        else if(instack[v])        {            low[u]=min(low[u],dfn[v]);        }    }    if(dfn[u]==low[u])    {        scc++;        while(1)        {            int tmp=sstack[top--];            addedge(scc,tmp,head3);            instack[tmp]=0;            belong[tmp]=scc;            if(tmp==u)            break;        }    }}void build(){    int i,j;    for(i=1;i<=2*n;i++)    {        for(j=head1[i];j!=-1;j=edge[j].next)        {            int v=edge[j].v;            if(belong[i]!=belong[v])            {                addedge(belong[v],belong[i],head2);            }        }    }}bool ok(int i,int j){    if(s[i]>=t[j]||t[i]<=s[j])    return false;    return true;}bool check(){    int i;    for(i=1;i<=n;i++)    {        if(belong[i<<1]==belong[i*2-1])        return false;    }    return true;}void topo(){    int i,j;    top=0;    stack<int> sta;    for(i=1;i<=scc;i++)    {        for(j=head2[i];j!=-1;j=edge[j].next)        {            d[edge[j].v]++;        }    }    for(i=1;i<=scc;i++)    {        if(!d[i])        sta.push(i);    }    while(!sta.empty())    {        int u=sta.top();        sta.pop();        seq[++top]=u;        for(i=head2[u];i!=-1;i=edge[i].next)        {            int v=edge[i].v;            d[v]--;            if(!d[v])            sta.push(v);        }    }}void paint(int u){    int k;    for(k=head2[u];k!=-1;k=edge[k].next)    {        if(col[edge[k].v]==0)        {            col[edge[k].v]=-1;            paint(edge[k].v);        }    }}void color(){    int i,j,k;    for(j=1;j<=top;j++)    {        int u=seq[j];        if(col[u]==0)        {            col[u]=1;            for(i=head3[u];i!=-1;i=edge[i].next)            {                int v=edge[i].v;                if(col[belong[((v-1)^1)+1]]==0)                {                    col[belong[((v-1)^1)+1]]=-1;                    paint(belong[((v-1)^1)+1]);                }            }        }    }}void print(){    int i,j;    for(i=1;i<=n;i++)    {        if(col[belong[i*2]]==1)        {            printf("%02d:%02d %02d:%02d\n",s[i*2]/60,s[i*2]%60,t[i*2]/60,t[i*2]%60);        }        else        {            printf("%02d:%02d %02d:%02d\n",s[i*2-1]/60,s[i*2-1]%60,t[i*2-1]/60,t[i*2-1]%60);        }    }}int main(){    freopen("in.txt","r",stdin);    int i,j;    scanf("%d",&n);    memset(head1,-1,sizeof(head1));    memset(head2,-1,sizeof(head2));    memset(head3,-1,sizeof(head3));    cnt=0;    for(i=1;i<=n;i++)    {        int u,v,tmp;        scanf("%d:%d",&u,&v);        s[2*i-1]=u*60+v;        scanf("%d:%d",&u,&v);        t[2*i]=u*60+v;        scanf("%d",&tmp);        t[2*i-1]=s[2*i-1]+tmp;        s[2*i]=t[2*i]-tmp;    }    for(i=1;i<=n;i++)    {        for(j=i+1;j<=n;j++)        {            if(ok(2*i,2*j))            {                addedge(2*i,2*j-1,head1);                addedge(2*j,2*i-1,head1);            }            if(ok(2*i-1,2*j)){addedge(2*i-1,2*j-1,head1);addedge(2*j,2*i,head1);}if(ok(2*i,2*j-1)){addedge(2*i,2*j,head1);addedge(2*j-1,2*i-1,head1);}if(ok(2*i-1,2*j-1)){addedge(2*i-1,2*j,head1);addedge(2*j-1,2*i,head1);}        }    }    scc=0;    for(i=1;i<=2*n;i++)    {        if(!dfn[i])        tarjan(i);    }    if(!check())    printf("NO\n");    else    {        printf("YES\n");        build();        topo();        color();        print();    }    return 0;}


 

 

 

 

原创粉丝点击