学习笔记(two sat)

关于two sat算法

关于具体算法
  • 首先此算法只对于存在类似于一个点选了另一个点就不能选这样的条件,并且每个点只有两种状态(一般是选或不选),不然是个NP问题
  • 大体做法就是先转换模型,把每个点拆成两个,一个代表取,一个代表不取,(注意:图中边代(u->v)代表取u就一定要取v)
  • 至于判断是否有可行解只要Tarjan缩点,如果一个点中两个状态的点在同一联通块中则无解,否则一定有可行解。
连边方法
  • A,B不能同时取:A->B' B->A‘
  • A,B必须反着取:A->B' A'->B B->A' B'->A
  • A,B不能都不取:A'->B B'->A
  • A,B必须同时取或不取:A->B B->A A'->B' B'->A'
  • 必须取A:A'->A
可行方案

Tarjan缩点判无解之后,重新反向建图,开个数组,将A与A‘所在联通块互相标记为敌人,tope DP的时候,依次将点取出,如果其没有颜色,则将其标记为true,同时将其的敌人标记为false即可

poj3207

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=1000+5;
bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
    T ans=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)&&ch!='-')ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
    return ans*f;
}
template<typename T>void write(T x,char y)
{
    if(x==0)
    {
        putchar('0');
        return;
    }
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    static char wr[20];
    int top=0;
    for(;x;x/=10)wr[++top]=x%10+'0';
    while(top)putchar(wr[top--]);
    putchar(y);
}
void file()
{
    #ifndef ONLINE_JUDGE
        freopen("3207.in","r",stdin);
        freopen("3207.out","w",stdout);
    #endif
}
int n,m;
struct edge
{
    int v,nex;
}e[N*N];
int head[N<<1],tt;
void add(int x,int y)
{
    ++tt;e[tt].v=y;e[tt].nex=head[x];head[x]=tt;
}
int lef[N],rig[N];
bool check(int i,int j)
{
    bool t1,t2;
    t1=(lef[i]<=lef[j]&&lef[j]<=rig[i]);
    t2=(lef[i]<=rig[j]&&rig[j]<=rig[i]);
    return t1^t2;
}
void build(int x)
{
    For(i,1,x-1)
    {
        if(check(i,x))
        {
            //cout<<i<<' '<<x<<endl;
            add(i,x+m);add(x,i+m);
            add(i+m,x);add(x+m,i);
        }
    }
}
void input()
{
    n=read<int>();m=read<int>();
    For(i,1,m)
    {
        lef[i]=read<int>()+1;
        rig[i]=read<int>()+1;
        if(lef[i]>rig[i])swap(lef[i],rig[i]);
        build(i);
    }
}
int low[N],dfn[N],dfs_clock;
int scc[N],id;
int l[N];
void Tarjan(int u)
{
    low[u]=dfn[u]=++dfs_clock;
    l[++l[0]]=u;
    int v;
    for(register int i=head[u];i;i=e[i].nex)
    {
        v=e[i].v;
        if(!dfn[v])
        {
            Tarjan(v);
            cmin(low[u],low[v]);
        }
        else if(!scc[v])
        {
            cmin(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        ++id;
        int k;
        do
        {
            k=l[l[0]--];
            scc[k]=id;
        }while(k^u);
    }
}
void work()
{
    For(i,1,m<<1)if(!dfn[i])Tarjan(i);
    /*For(i,1,m)
    {
        printf("%d %d\n",scc[i],scc[i+m]);
    }*/
    For(i,1,m)
    {
        if(scc[i]==scc[i+m])
        {
            puts("the evil panda is lying again");
            return;
        }
    }
    puts("panda is telling the truth...");
}
int main()
{
    file();
    input();
    work();
    return 0;
}

poj3678

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=1e4+5,M=1e6+5;
bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
    T ans=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)&&ch!='-')ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
    return ans*f;
}
template<typename T>void write(T x,char y)
{
    if(x==0)
    {
        putchar('0');
        return;
    }
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    static char wr[20];
    int top=0;
    for(;x;x/=10)wr[++top]=x%10+'0';
    while(top)putchar(wr[top--]);
    putchar(y);
}
void file()
{
    #ifndef ONLINE_JUDGE
        freopen("3678.in","r",stdin);
        freopen("3678.out","w",stdout);
    #endif
}
struct edge
{
    int v,nex;
}e[M<<2];
int head[N<<1],tt;
int n,m;
void add(int x,int y)
{
    ++tt;e[tt].v=y;e[tt].nex=head[x];head[x]=tt;
}
void input()
{
    int a,b,c;
    char opt[10];
    n=read<int>();m=read<int>();
    For(i,1,m)
    {
        a=read<int>()+1;b=read<int>()+1;c=read<int>();
        scanf("%s",opt);
        if(opt[0]=='A')
        {
            if(c)add(a+n,a),add(b+n,b),add(a,b),add(b,a);
            else if(!c)add(a,b+n),add(b,a+n);
        }
        else if(opt[0]=='O')
        {
            if(c)add(a+n,b),add(b+n,a);
            else if(!c)add(a,a+n),add(b,b+n);
        }
        else if(opt[0]=='X')
        {
            if(c)add(a,b+n),add(a+n,b),add(b,a+n),add(b+n,a);
            else if(!c)add(a,b),add(b,a),add(a+n,b+n),add(b+n,a+n);
        }
    }
}
int dfn[N<<1],low[N<<1],l[N<<1],dfs_clock,scc[N<<1],id;
void Tarjan(int u)
{
    low[u]=dfn[u]=++dfs_clock;l[++l[0]]=u;
    int v;
    for(register int i=head[u];i;i=e[i].nex)
    {
        v=e[i].v;
        if(!dfn[v])
        {
            Tarjan(v);
            cmin(low[u],low[v]);
        }
        else if(!scc[v])
        {
            cmin(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        int k;
        id++;
        do
        {
            k=l[l[0]--];
            scc[k]=id;
        }while(k^u);
    }
}
void work()
{
    For(i,1,n)if(!dfn[i])Tarjan(i);
    For(i,1,n)
    {
        if(scc[i]==scc[i+n]){puts("NO");return;}
    }
    puts("YES");
}
int main()
{
    file();
    input();
    work();
    return 0;
}

poj3683

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=5e3+5;
bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
    T ans=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)&&ch!='-')ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
    return ans*f;
}
template<typename T>void write(T x,char y)
{
    if(x==0)
    {
        putchar('0');putchar('0');putchar(y);
        return;
    }
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x<10)putchar('0');
    static char wr[20];
    int top=0;
    for(;x;x/=10)wr[++top]=x%10+'0';
    while(top)putchar(wr[top--]);
    putchar(y);
}
void file()
{
    #ifndef ONLINE_JUDGE
        freopen("3683.in","r",stdin);
        freopen("3683.out","w",stdout);
    #endif
}
struct edge
{
    int u,v,nex;
}e[N*N];
int head[N<<1],tt;
int n;
void add(int x,int y)
{
    ++tt;e[tt].u=x;e[tt].v=y;e[tt].nex=head[x];head[x]=tt;
}
int st[N][5],ed[N][5],las[N];
void deal(int i)
{
    st[i][4]+=las[i];
    st[i][3]+=st[i][4]/60;
    st[i][4]%=60;

    ed[i][2]-=las[i];
    while(ed[i][2]<0)
    {
        ed[i][2]+=60;
        ed[i][1]-=1;
    }
}
bool early(int t1,int t2,int t3,int t4,bool flag)
{
    if(t1<t3)return 1;
    if(t1==t3&&t2<t4)return 1;
    if(flag&&t1==t3&&t2==t4)return 1;
    return 0;
}
void build()
{
    For(i,1,n)For(x,1,n)
    {
        if(i==x)continue;
        if(early(st[i][1],st[i][2],st[x][1],st[x][2],1))
            if(early(st[x][1],st[x][2],st[i][3],st[i][4],0))
                add(i,x+n),add(x,i+n);

        if(early(ed[i][1],ed[i][2],st[x][1],st[x][2],1))
            if(early(st[x][1],st[x][2],ed[i][3],ed[i][4],0))
                add(i+n,x+n),add(x,i);
        
        if(early(ed[i][1],ed[i][2],ed[x][1],ed[x][2],1))
            if(early(ed[x][1],ed[x][2],ed[i][3],ed[i][4],0))
                add(i+n,x),add(x+n,i);
        
        if(early(st[i][1],st[i][2],ed[x][1],ed[x][2],1))
            if(early(ed[x][1],ed[x][2],st[i][3],st[i][4],0))
                add(i,x),add(x+n,i+n);
    }
}
void input()
{
    n=read<int>();
    For(i,1,n)
    {
        st[i][1]=st[i][3]=read<int>();st[i][2]=st[i][4]=read<int>();
        ed[i][1]=ed[i][3]=read<int>();ed[i][2]=ed[i][4]=read<int>();
        las[i]=read<int>();
        deal(i);
    }
}
int dfn[N<<1],low[N<<1],l[N<<1],dfs_clock,scc[N<<1],id;
void Tarjan(int u)
{
    low[u]=dfn[u]=++dfs_clock;l[++l[0]]=u;
    int v;
    for(register int i=head[u];i;i=e[i].nex)
    {
        v=e[i].v;
        if(!dfn[v])
        {
            Tarjan(v);
            cmin(low[u],low[v]);
        }
        else if(!scc[v])
        {
            cmin(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        int k;
        id++;
        do
        {
            k=l[l[0]--];
            scc[k]=id;
        }while(k^u);
    }
}
int beg[N<<1],nex[N<<1],to[N<<1],E,cf[N<<1],in[N<<1];
void add_new(int x,int y)
{
    ++E;to[E]=y;nex[E]=beg[x];beg[x]=E;
}
void rebuild()
{
    int u,v;
    For(i,1,tt)
    {
        u=scc[e[i].u];v=scc[e[i].v];
        if(u^v)
        {
            add_new(v,u);in[u]++;
        }
    }
    For(i,1,n)
    {
        cf[scc[i]]=scc[i+n];
        cf[scc[i+n]]=scc[i];
    }
}
queue<int>q;
int cl[N<<1];
void topesort()
{
    int u;
    For(i,1,n<<1)if(!in[i])q.push(i);
    while(!q.empty())
    {
        u=q.front();q.pop();
        if(cl[u]==0)cl[u]=1,cl[cf[u]]=-1;
        for(register int i=beg[u];i;i=nex[i])
        {
            if(!--in[to[i]])q.push(to[i]);
        }
    }
}
void out()
{
    For(i,1,n)
    {
        if(cl[scc[i]]==1)
        {
            write(st[i][1],':');write(st[i][2],' ');
            write(st[i][3],':');write(st[i][4],'\n');
        }
        else if(cl[scc[i+n]]==1)
        {
            write(ed[i][1],':');write(ed[i][2],' ');
            write(ed[i][3],':');write(ed[i][4],'\n');
        }
    }
}
void work()
{
    For(i,1,n<<1)if(!dfn[i])Tarjan(i);
    For(i,1,n)
    {
        if(scc[i]==scc[i+n]){puts("NO");return;}
    }
    puts("YES");
    rebuild();
    topesort();
    out();
}
int main()
{
    file();
    input();
    build();
    work();
    return 0;
}

POJ2723

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=2e3+5;
bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
    T ans=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)&&ch!='-')ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
    return ans*f;
}
template<typename T>void write(T x,char y)
{
    if(x==0)
    {
        putchar('0');putchar(y);
        return;
    }
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    static char wr[20];
    int top=0;
    for(;x;x/=10)wr[++top]=x%10+'0';
    while(top)putchar(wr[top--]);
    putchar(y);
}
void file()
{
    #ifndef ONLINE_JUDGE
        freopen("2723.in","r",stdin);
        freopen("2723.out","w",stdout);
    #endif
}
struct edge
{
    int v,nex;
}e[N*N];
int head[N<<1],tt;
int n,m;
int key[N];
void add(int x,int y)
{
    ++tt;e[tt].v=y;e[tt].nex=head[x];head[x]=tt;
}
int a[N],b[N];
void input()
{
    int x,y;
    For(i,0,n-1)
    {
        x=read<int>();y=read<int>();
        key[x]=i<<1;key[y]=key[x]|1;
    }
    For(i,1,m)
    {
        a[i]=read<int>();b[i]=read<int>();
    }
}
int dfn[N<<1],low[N<<1],scc[N<<1],id,dfs_clock;
int l[N<<1];
void build(int mid)
{
    int x,y;
    tt=0;dfs_clock=id=0;
    memset(head,-1,sizeof head);
    memset(dfn,0,sizeof dfn);
    memset(low,0,sizeof low);
    memset(scc,0,sizeof scc);
    For(i,1,mid)
    {
        x=a[i];y=b[i];
        if(x==y)add(key[x]^1,key[x]);
        else
        {
            add(key[x]^1,key[y]);
            add(key[y]^1,key[x]);
        }
    }
}
void Tarjan(int u)
{
    low[u]=dfn[u]=++dfs_clock;
    l[++l[0]]=u;
    int v;
    for(register int i=head[u];i!=-1;i=e[i].nex)
    {
        v=e[i].v;
        if(!dfn[v])
        {
            Tarjan(v);
            cmin(low[u],low[v]);
        }
        else if(!scc[v])cmin(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        int k;
        ++id;
        do
        {
            k=l[l[0]--];
            scc[k]=id;
        }while(k^u);
    }
}
bool check(int mid)
{
    build(mid);
    For(i,1,n<<1)if(!dfn[i])Tarjan(i);
    for(int i=0;i<=n*2-1;i+=2)
    {
        if(scc[i]==scc[i^1])return 0;
    }
    return 1;
}
void work()
{
    int ans=0,l=1,r=m,mid;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid))ans=mid,l=mid+1;
        else r=mid-1;
    }
    write(ans,'\n');
}
int main()
{
    file();
    while(scanf("%d%d",&n,&m))
    {
        if(n<=0&&m<=0)break;
        input();
        work();
    }
    return 0;
}

转载于:https://www.cnblogs.com/dengyixuan/p/8251265.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值