zoukankan      html  css  js  c++  java
  • zoj 3656 2-sat 不错的题

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?

    problemId=4879


    TLE了一下午。然后没办法了 去搜题解 发现思路跟我的差点儿相同 可是就是我的T  后来扩大了数组 然后AC,无语啊

    按我的估算 500个点 开到1000+就够了  可是不够 奇怪不懂......

    YES or NO的题,一般就是并查集跟2-sat了 目測这道题并查集写起来更easy

    http://blog.csdn.net/u011026968/article/details/10823853

    看着道题  poj 3678  看完就能发现,仅仅要将每一位都当做poj3678 执行32次 然后就OK

    建图方法跟poj3678一样

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <stack>
    #include <iostream>
    using namespace std;
    
    
    #define CL(a,b) memset(a,b,sizeof(a))
    #define IN(s) freopen(s,"r",stdin)
    
    const int MAXN = 6000;
    int n,b[505][505];
    int head[MAXN],dfn[MAXN],low[MAXN],id[MAXN];
    int cnt,scnt;
    stack<int>st;
    struct Node{
        int to,nxt;
    }edge[1000010];///
    
    
    inline void addedge(int u,int v,int k)
    {
        edge[k].to=v;
        edge[k].nxt=head[u];
        head[u]=k;
        //printf("u=%d v=%d k=%d
    ",u,v,k);
    }
    void tarjan(int u)
    {
        int v,i,min1=dfn[u]=low[u]=cnt++;
        st.push(u);
        for(i=head[u];i!=-1;i=edge[i].nxt)
        {
            v=edge[i].to;
            if(dfn[v]==-1)tarjan(v);
            min1=min(min1,low[v]);
        }
        if(min1<low[u]){low[u]=min1;return;}
        do
        {
            v=st.top();
            id[v]=scnt;
            st.pop();
            low[v]=n*2;
        }while(v!=u);
        scnt++;
    }
    
    int solve(int pos)
    {
        CL(dfn,0xff);
        CL(id,0xff);
        CL(head,0xff);
        CL(low,0xff);
    
        scnt=cnt=0;
        while(!st.empty())st.pop();
        int num=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                if(i==j)continue;///
                int f= (b[i][j]>>pos)&1;
                //////////
                //printf("pos=%d bij=%d f=%d
    ",pos,b[i][j],f);
                if(i%2 && j%2)
                {
                    if(f)
                    {
                        addedge(i,j+n,num++);
                        addedge(j,i+n,num++);
    
                    }
                    else
                    {
    
                        addedge(i+n,i,num++);
                        addedge(j+n,j,num++);
                        addedge(i,j,num++);
                        addedge(j,i,num++);
                    }
                    continue;
                }
                if(i%2==0 && j%2==0)
                {
                    if(f)
                    {
    
                        addedge(i,i+n,num++);
                        addedge(j,j+n,num++);
                        addedge(i+n,j+n,num++);
                        addedge(j+n,i+n,num++);
                    }
                    else
                    {
    
                        addedge(j+n,i,num++);
                        addedge(i+n,j,num++);
                    }
                    continue;
                }
                if(f)
                {
                    addedge(i,j+n,num++);
                    addedge(j+n,i,num++);
                    addedge(j,i+n,num++);
                    addedge(i+n,j,num++);
                }
                else
                {
                    addedge(i,j,num++);
                    addedge(j,i,num++);
                    addedge(i+n,j+n,num++);
                    addedge(j+n,i+n,num++);
                }
            }
        int flag=1;
        for(int i=0;i<n*2;i++)
            if(dfn[i] == -1)
            {
                ////////
                //printf("tari=%d
    ",i);
                ////////
                tarjan(i);
            }
    
        for(int i=0;i<n;i++)
            if(id[i] == id[i+n])//在同一个连通分量
            {
                flag=0;
                break;
            }
        if(flag)return 1;
        else return 0;
    }
    
    int main()
    {
        //IN("zoj3656.txt");
        while(~scanf("%d",&n))
        {
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    scanf("%d",&b[i][j]);
            int flag=0;
            for(int i=0;i<n;i++)
            {
                if(b[i][i])
                {
                    flag=2;
                    puts("NO");
                    break;
                }
            }
            if(flag==2)continue;
            for(int i=0;i<n-1;i++)
                for(int j=i+1;j<n;j++)
                {
                    if(b[i][j]!=b[j][i])
                    {
                        flag=2;
                        puts("NO");
                        break;
                    }
                }
            if(flag==2)continue;
            for(int i=0;i<32;i++)
            {
                flag=solve(i);
                if(flag==0)break;
            }
            if(!flag)puts("NO");
            else puts("YES");
        }
        return 0;
    }
    


    并查集的做法代码短了非常多 好流弊的样子  http://blog.csdn.net/lasolmi/article/details/38979207


    另一种建图方法,网上找的  快了20ms  不是非常理解的说

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <stack>
    #include <iostream>
    using namespace std;
    
    
    #define CL(a,b) memset(a,b,sizeof(a))
    #define IN(s) freopen(s,"r",stdin)
    
    const int MAXN = 6000;
    int n,b[505][505];
    int head[MAXN],dfn[MAXN],low[MAXN],id[MAXN];
    int cnt,scnt;
    stack<int>st;
    struct Node{
        int to,nxt;
    }edge[1000010];///
    
    
    inline void addedge(int u,int v,int k)
    {
        edge[k].to=v;
        edge[k].nxt=head[u];
        head[u]=k;
        //printf("u=%d v=%d k=%d
    ",u,v,k);
    }
    void tarjan(int u)
    {
        int v,i,min1=dfn[u]=low[u]=cnt++;
        st.push(u);
        for(i=head[u];i!=-1;i=edge[i].nxt)
        {
            v=edge[i].to;
            if(dfn[v]==-1)tarjan(v);
            min1=min(min1,low[v]);
        }
        if(min1<low[u]){low[u]=min1;return;}
        do
        {
            v=st.top();
            id[v]=scnt;
            st.pop();
            low[v]=n*2;
        }while(v!=u);
        scnt++;
    }
    
    int solve(int pos)
    {
        CL(dfn,0xff);
        CL(id,0xff);
        CL(head,0xff);
        CL(low,0xff);
    
        scnt=cnt=0;
        while(!st.empty())st.pop();
        int num=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                if(i==j)continue;///
                int f= (b[i][j]>>pos)&1;
                //////////
                //printf("pos=%d bij=%d f=%d
    ",pos,b[i][j],f);
                if(i%2 && j%2)
                {
                    if(f)
                    {
                        //addedge(i,j+n,num++);
                        //addedge(j,i+n,num++);
                        addedge(i+n,j,num++);
                        addedge(j+n,i,num++);
                    }
                    else
                    {
                        addedge(i,i+n,num++);
                        addedge(j,j+n,num++);
                        //addedge(i+n,i,num++);
                        //addedge(j+n,j,num++);
                        //addedge(i,j,num++);
                        //addedge(j,i,num++);
                    }
                    continue;
                }
                if(i%2==0 && j%2==0)
                {
                    if(f)
                    {
                        addedge(i+n,i,num++);
                        addedge(j+n,j,num++);
    
                        //addedge(i,i+n,num++);
                        //addedge(j,j+n,num++);
                        //addedge(i+n,j+n,num++);
                        //addedge(j+n,i+n,num++);
                    }
                    else
                    {
                        addedge(i,j+n,num++);
                        addedge(j,i+n,num++);
                        //addedge(j+n,i,num++);
                        //addedge(i+n,j,num++);
                    }
                    continue;
                }
                if(f)
                {
                    addedge(i,j+n,num++);
                    addedge(j+n,i,num++);
                    addedge(j,i+n,num++);
                    addedge(i+n,j,num++);
                }
                else
                {
                    addedge(i,j,num++);
                    addedge(j,i,num++);
                    addedge(i+n,j+n,num++);
                    addedge(j+n,i+n,num++);
                }
            }
        int flag=1;
        for(int i=0;i<n*2;i++)
            if(dfn[i] == -1)
            {
                ////////
                //printf("tari=%d
    ",i);
                ////////
                tarjan(i);
            }
    
        for(int i=0;i<n;i++)
            if(id[i] == id[i+n])//在同一个连通分量
            {
                flag=0;
                break;
            }
        if(flag)return 1;
        else return 0;
    }
    
    int main()
    {
        //IN("zoj3656.txt");
        while(~scanf("%d",&n))
        {
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    scanf("%d",&b[i][j]);
            int flag=0;
            for(int i=0;i<n;i++)
            {
                if(b[i][i])
                {
                    flag=2;
                    puts("NO");
                    break;
                }
            }
            if(flag==2)continue;
            for(int i=0;i<n-1;i++)
                for(int j=i+1;j<n;j++)
                {
                    if(b[i][j]!=b[j][i])
                    {
                        flag=2;
                        puts("NO");
                        break;
                    }
                }
            if(flag==2)continue;
            for(int i=0;i<32;i++)
            {
                flag=solve(i);
                if(flag==0)break;
            }
            if(!flag)puts("NO");
            else puts("YES");
        }
        return 0;
    }
    



  • 相关阅读:
    ClickHouse 监控及备份 (三)ClickHouse 配置
    ClickHouse 监控及备份 (二)Prometheus&Grafana 的安装
    ClickHouse 监控及备份 (一)ClickHouse 监控概述
    ClickHouse 高级(八)运维(1)常见问题排查
    ClickHouse 高级(七)MaterializeMySQL 引擎
    ClickHouse 高级(六)物化视图
    使用Iperf调整网络
    WinForm中DataGridView的使用(四)
    数据库设计经验总结
    WinForm使用Label控件模拟分割线(竖向)
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5202003.html
Copyright © 2011-2022 走看看