zoukankan      html  css  js  c++  java
  • 2-sat

    http://blog.sina.com.cn/s/blog_64675f540100k2xj.html

    http://www.cppblog.com/MatoNo1/archive/2011/07/13/150766.aspx

    讲解看的这两篇博客,其实最好直接去看国家集训队的论文,别的抄来抄去想找个原始出处都难,不过我也没什么原则说这话就对了。。

    求出强连通分量后进行缩点,新图是dag图,具有拓扑性质,直接在上面进行染色

    http://acm.hdu.edu.cn/showproblem.php?pid=3062

    2-sat判定性,复杂度O(M)

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <map>
    using namespace std ;
    struct node 
    {
        int s,t,nxt ;
    }e[4000005] ;
    int n,m,idx,ans,tp,cnt,dfn[100005],vis[100005],low[100005],head[100005],st[100005],belong[100005] ;
    void add(int s,int t)
    {
        e[cnt].s=s ;
        e[cnt].t=t ;
        e[cnt].nxt=head[s] ;
        head[s]=cnt++ ;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=++idx ;
        vis[u]=1 ;
        st[++tp]=u ;
        int v ;
        for(int i=head[u] ;i!=-1 ;i=e[i].nxt)
        {
            v=e[i].t ;
            if(!dfn[v])
            {
                tarjan(v) ;
                low[u]=min(low[u],low[v]) ;
            }
            else if(vis[v])
                low[u]=min(low[u],dfn[v]) ;
        }
        if(dfn[u]==low[u])
        {
            ans++ ;
            while(1)
            {
                v=st[tp--] ;
                vis[v]=0 ;
                belong[v]=ans ;
                if(v==u)break ;
            }
        }
    }
    bool _2sat()
    {
        memset(vis,0,sizeof(vis)) ;
        memset(dfn,0,sizeof(dfn)) ;
        idx=tp=ans=0 ;
        for(int i=0 ;i<2*n ;i++)
            if(!dfn[i])
                tarjan(i) ;
        for(int i=0 ;i<n ;i++)
            if(belong[2*i]==belong[(2*i)^1])
                return false ;
        return true ;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            cnt=0 ;
            memset(head,-1,sizeof(head)) ;
            while(m--)
            {
                int a,b,c,d ;
                scanf("%d%d%d%d",&a,&b,&c,&d) ;
                int u,v ;
                u=a*2+c ;v=b*2+d ;
                add(u,v^1) ;add(v,u^1) ; 
            }
            if(_2sat())puts("YES") ;
            else puts("NO") ;
        }
        return 0 ;
    }
    View Code

    http://acm.hit.edu.cn/hoj/problem/view?id=1917

    2-sat判定性,且能输出任意一组解,解法见赵爽的集训队论文,复杂度O(M)

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <map>
    using namespace std ;
    struct node 
    {
        int s,t,nxt ;
    }e[400005],dag[400005] ;
    int n,m,idx,ans,tp,cnt,dfn[100005],vis[100005],low[100005],head[100005],st[100005],belong[100005] ;
    void add(int s,int t)
    {
        e[cnt].s=s ;e[cnt].t=t ;e[cnt].nxt=head[s] ;head[s]=cnt++ ;
    }
    int cntdag,headdag[100005] ;
    void adddag(int s,int t)
    {
        dag[cnt].s=s ;dag[cnt].t=t ;dag[cnt].nxt=head[s] ;headdag[s]=cntdag++ ;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=++idx ;
        vis[u]=1 ;
        st[++tp]=u ;
        int v ;
        for(int i=head[u] ;i!=-1 ;i=e[i].nxt)
        {
            v=e[i].t ;
            if(!dfn[v])
            {
                tarjan(v) ;
                low[u]=min(low[u],low[v]) ;
            }
            else if(vis[v])
                low[u]=min(low[u],dfn[v]) ;
        }
        if(dfn[u]==low[u])
        {
            ans++ ;
            while(1)
            {
                v=st[tp--] ;
                vis[v]=0 ;
                belong[v]=ans ;
                if(v==u)break ;
            }
        }
    }
    void builddag()
    {
        cntdag=0 ;
        memset(headdag,-1,sizeof(headdag)) ;
        for(int i=0 ;i<2*n ;i++)
        {
            for(int j=headdag[i] ;j!=-1 ;j=dag[j].nxt)
            {
                int v=e[j].t ;
                if(belong[v]!=belong[i])//缩点 
                    adddag(belong[v],belong[i]) ;//建立反向边
            }
        }
    }
    int color[100005],cp[100005] ;
    void bfs()//染色 
    {
        memset(color,0,sizeof(color)) ;
        queue <int> q ;
        for(int i=1 ;i<=ans ;i++)
            q.push(i) ;
        while(!q.empty())
        {
            int u=q.front() ;
            q.pop() ;
            if(!color[u])
            {
                color[u]=1 ;
                color[cp[u]]=-1 ; 
            }
            for(int i=headdag[u] ;i!=-1 ;i=dag[i].nxt)
            {
                int v=dag[i].t ;
                q.push(v) ;
            }
        } 
    }
    void _2sat()
    {
        memset(vis,0,sizeof(vis)) ;
        memset(dfn,0,sizeof(dfn)) ;
        idx=tp=ans=0 ;
        for(int i=0 ;i<2*n ;i++)
            if(!dfn[i])
                tarjan(i) ;
        for(int i=0 ;i<n ;i++)
        {
            if(belong[2*i]==belong[(2*i)^1])
            {
                puts("NIE") ;
                return ;
            }
            else
            {
                cp[belong[i*2]]=belong[(i*2)^1] ;
                cp[belong[(i*2)^1]]=belong[i*2] ;
            }
        }
        builddag() ;
        bfs() ;
        for(int i=0 ;i<2*n ;i+=2)
        {
            if(color[belong[i]]==1)
                printf("%d
    ",i+1) ;
            else 
                printf("%d
    ",i+2) ;
        }
        return ;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            cnt=0 ;
            memset(head,-1,sizeof(head)) ;
            while(m--)
            {
                int a,b ;
                scanf("%d%d",&a,&b) ;
                a-- ;b-- ;
                add(a,b^1) ;add(b,a^1) ; 
            }
            _2sat() ;
        }
        return 0 ;
    }
    View Code

    http://acm.hdu.edu.cn/showproblem.php?pid=1814

    2-sat判定且能输出字典序最小的一组解,复杂度O(NM)

    不过这个做法我还没看,已经快吐了,先放到这里不管 

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    #define re(i, n) for (int i=0; i<n; i++)
    const int MAXN = 20000, MAXM = 100000, INF = ~0U >> 2;
    struct node {
        int a, b, pre, next;
    } E[MAXM], E2[MAXM];
    int _n, n, m, V[MAXN], ST[MAXN][2], Q[MAXN], Q2[MAXN], vst[MAXN];
    bool res_ex;
    void init_d()
    {
        re(i, n) E[i].a = E[i].pre = E[i].next = E2[i].a = E2[i].pre = E2[i].next = i;
        m = n;
    }
    void add_edge(int a, int b)
    {
        E[m].a = a; E[m].b = b; E[m].pre = E[a].pre; E[m].next = a; E[a].pre = m; E[E[m].pre].next = m;
        E2[m].a = b; E2[m].b = a; E2[m].pre = E2[b].pre; E2[m].next = b; E2[b].pre = m; E2[E2[m].pre].next = m++;
    }
    void solve()
    {
        re(i, n) {V[i] = 0; vst[i] = 0;} res_ex = 1;
        int i, i1, i2, j, k, len, front, rear, front2, rear2;
        bool ff;
        re(_i, _n) {
            if (V[_i << 1] == 1 || V[(_i << 1) + 1] == 1) continue;
            i = _i << 1; len = 0;
            if (!V[i]) {
                ST[len][0] = i; ST[len++][1] = 1; if (!V[i ^ 1]) {ST[len][0] = i ^ 1; ST[len++][1] = 2;}
                Q[front = rear = 0] = i; vst[i] = i1 = n + i; Q2[front2 = rear2 = 0] = i ^ 1; vst[i ^ 1] = i2 = (n << 1) + i; ff = 1;
                for (; front<=rear; front++) {
                    j = Q[front];
                    for (int p = E[j].next; p != j; p=E[p].next) {
                        k = E[p].b;
                        if (V[k] == 2 || vst[k] == i2 || V[k ^ 1] == 1 || vst[k ^ 1] == i1) {ff = 0; break;}
                        if (vst[k] != i1) {
                            Q[++rear] = k; vst[k] = i1;
                            if (!V[k]) {ST[len][0] = k; ST[len++][1] = 1;}
                        }
                        if (vst[k ^ 1] != i2) {
                            Q2[++rear2] = k ^ 1; vst[k ^ 1] = i2;
                            if (!V[k]) {ST[len][0] = k ^ 1; ST[len++][1] = 2;}
                        }
                    }
                    if (!ff) break;
                }
                if (ff) {
                    for (; front2<=rear2; front2++) {
                        j = Q2[front2];
                        for (int p = E2[j].next; p != j; p=E2[p].next) {
                            k = E2[p].b;
                            if (V[k] == 1 || vst[k] == i1) {ff = 0; break;}
                            if (vst[k] != i2) {
                                vst[k] = i2; Q2[++rear] = k;
                                if (!V[k]) {ST[len][0] = k; ST[len++][1] = 2;}
                            }
                        }
                        if (!ff) break;
                    }
                    if (ff) {
                        re(j, len) V[ST[j][0]] = ST[j][1];
                        continue;
                    }
                }
            }
            i = (_i << 1) + 1; len = 0;
            if (!V[i]) {
                ST[len][0] = i; ST[len++][1] = 1; if (!V[i ^ 1]) {ST[len][0] = i ^ 1; ST[len++][1] = 2;}
                Q[front = rear = 0] = i; vst[i] = i1 = n + i; Q2[front2 = rear2 = 0] = i ^ 1; vst[i ^ 1] = i2 = (n << 1) + i; ff = 1;
                for (; front<=rear; front++) {
                    j = Q[front];
                    for (int p = E[j].next; p != j; p=E[p].next) {
                        k = E[p].b;
                        if (V[k] == 2 || vst[k] == i2 || V[k ^ 1] == 1 || vst[k ^ 1] == i1) {ff = 0; break;}
                        if (vst[k] != i1) {
                            Q[++rear] = k; vst[k] = i1;
                            if (!V[k]) {ST[len][0] = k; ST[len++][1] = 1;}
                        }
                        if (vst[k ^ 1] != i2) {
                            Q2[++rear2] = k ^ 1; vst[k ^ 1] = i2;
                            if (!V[k]) {ST[len][0] = k ^ 1; ST[len++][1] = 2;}
                        }
                    }
                    if (!ff) break;
                }
                if (ff) {
                    for (; front2<=rear2; front2++) {
                        j = Q2[front2];
                        for (int p = E2[j].next; p != j; p=E2[p].next) {
                            k = E2[p].b;
                            if (V[k] == 1 || vst[k] == i1) {ff = 0; break;}
                            if (vst[k] != i2) {
                                vst[k] = i2; Q2[++rear] = k;
                                if (!V[k]) {ST[len][0] = k; ST[len++][1] = 2;}
                            }
                        }
                        if (!ff) break;
                    }
                    if (ff) {
                        re(j, len) V[ST[j][0]] = ST[j][1];
                        continue;
                    }
                }
            }
            if (V[_i << 1] + V[(_i << 1) + 1] != 3) {res_ex = 0; break;}
        }
    }
    int main()
    {
        int _m, a, b;
        while (scanf("%d%d", &_n, &_m) != EOF) {
            n = _n << 1; init_d();
            re(i, _m) {
                scanf("%d%d", &a, &b); a--; b--;
                if (a != (b ^ 1)) {add_edge(a, b ^ 1); add_edge(b, a ^ 1);}
            }
            solve();
            if (res_ex) {re(i, n) if (V[i] == 1) printf("%d
    ", i + 1);} else puts("NIE");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    maven_常用命令
    tomcat_server.xml常用配置
    tomcat线程池原理
    Tomcat处理HTTP请求原理&线程池
    javaweb-javaScript(一)
    javaweb-html快速入门
    javaweb-css
    javaweb-单元测试与注解
    javaweb-文件的上传下载
    javaweb-jsp开发模式+JSON插件
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/3714218.html
Copyright © 2011-2022 走看看