• 2-SAT入门


      大概学了一下2-SAT,写了一道模板和一道USACO

      输出一个方案的话,tarjan缩点后倒着拓扑,染色输出。

      求任何解下选哪个就得枚举每个点dfs来判断选哪个。  

    HIT 1917(2-sat模板)

    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<map>
    #define ll long long 
    using namespace std;
    const int maxn=16010,inf=1e9;
    struct poi{int too,pre,x;}e[maxn*10],e2[maxn*10];
    int last[maxn],last2[maxn],dfn[maxn],low[maxn],col[maxn],lack[maxn],ru[maxn],rs[maxn],st[maxn],op[maxn];
    int n,m,x,y,z,tot,tot2,tott,top,color,flag;
    void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;}
    void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;}
    int next(int x){return x&1?x+1:x-1;}
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
        for(int i=last[x];i;i=e[i].pre)
        if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
        else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
        if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color;
    }
    void topsort()
    {
        top=0;for(int i=1;i<=color;i++)if(!ru[i])st[++top]=i;
        while(top)
        {
            int now=st[top--];
            if(!rs[now])rs[now]=1,rs[op[now]]=2;
            for(int i=last2[now];i;i=e2[i].pre)
            if(!(--ru[e2[i].too]))st[++top]=e2[i].too;
        }
    }
    void clr()
    {
        color=top=tot=tot2=flag=0;
        memset(col,0,sizeof(col));
        memset(dfn,0,sizeof(dfn));
        memset(ru,0,sizeof(ru));
        memset(rs,0,sizeof(rs));
        memset(lack,0,sizeof(lack));
        memset(last,0,sizeof(last));
        memset(last2,0,sizeof(last2));
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            clr();
            for(int i=1;i<=m;i++)read(x),read(y),add(x,next(y)),add(y,next(x));
            for(int i=1;i<=2*n;i++)if(!dfn[i])tarjan(i);
            for(int i=1;i<=n;i++)if(col[i<<1]==col[next(i<<1)]){printf("NIE
    ");flag=1;break;}
            else op[col[i<<1]]=col[next(i<<1)],op[col[next(i<<1)]]=col[i<<1];
            if(flag)continue;
            for(int i=1;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].too],col[e[i].x]),ru[col[e[i].x]]++;
            topsort();
            for(int i=1;i<=n;i++)if(rs[col[(i<<1)]]==1)printf("%d
    ",i<<1);else printf("%d
    ",next(i<<1));
        }
        return 0;
    }
    View Code

    bzoj 2199

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    const int maxn=500010;
    struct poi{int x,too,pre;}e[maxn],e2[maxn];
    int n,m,t,tot,tot2,tott,top,color;
    int dfn[maxn],low[maxn],col[maxn],last[maxn],last2[maxn],v[maxn],st[maxn],lack[maxn];
    char ans[maxn];
    void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;   
    }
    int readd()
    {
        int x;read(x);char c=getchar();
        while(c!='Y'&&c!='N')c=getchar(); 
        if(c=='Y')return (x<<1)^1;
        return x<<1;
    }
    void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;}
    void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;}
    void dfs(int x)
    {
        v[x]=t;
        for(int i=last2[x];i;i=e2[i].pre)
        if(v[e2[i].too]!=t)dfs(e2[i].too);
    }
    bool check(int x)
    {
        t++;dfs(x);
        for(int i=1;i<=n;i++)
        if(v[col[(i<<1)^1]]==t&&v[col[i<<1]]==t)return 0;
        return 1;
    }
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
        for(int i=last[x];i;i=e[i].pre)
        if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
        else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
        if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color;
    }
    void dfss(int x)
    {
        v[x]=1;
        for(int i=last[x];i;i=e[i].pre)
        if(!v[e[i].too])dfss(e[i].too);
    }
    int main()
    {
        read(n);read(m);
        for(int i=1;i<=m;i++)
        {
            int x=readd(),y=readd();
            add(x^1,y);add(y^1,x);
        }
        for(int i=2;i<=((n<<1)^1);i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=n;i++)if(col[(i<<1)^1]==col[i<<1]){puts("IMPOSSIBLE");return 0;}
        for(int i=1;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].x],col[e[i].too]);
        for(int i=1;i<=n;i++)
        {
            int x=check(col[(i<<1)^1]),y=check(col[i<<1]);
            if(!(x||y)){puts("IMPOSSIBLE");return 0;}
            else if(x&&y)ans[i]='?';
            else if(x)ans[i]='Y';
            else if(y)ans[i]='N';
        }
        for(int i=1;i<=n;i++)putchar(ans[i]);
    }
    View Code

     

  • 相关阅读:
    linux 常用命令大全
    socket的读写函数readn和writen函数
    python中exec 和eval的用法
    python中set集合介绍
    python中下划线变量的规则和意义
    关于小端字节序和大端字节序的解释
    需要学习的网站
    关于尾递归节省内存空间
    python中的with语句
    python中的类变量和对象变量,以及传值传引用的探究
  • 原文地址:https://www.cnblogs.com/Sakits/p/7161787.html
Copyright © 2020-2023  润新知