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\n",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\n",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\n",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\n",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\n",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\n",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;
}
时间: 2024-10-11 15:07:36

zoj 3656 2-sat 不错的题的相关文章

HDU1160:FatMouse&#39;s Speed(最长上升子序列,不错的题)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1160 学的东西还是不深入啊,明明会最长上升子序列,可是还是没有A出这题,反而做的一点思路没有,题意就不多说了,真是怀疑了为什么做这题的时候竟然想用nlog(n)的那个算法, 根本不可能有解啊,真想抽自己一下,最后无奈看了题解,发现他们写的非常棒,记录路径仅用一个数组就可以实现,可惜我没有想到啊,还是做题不深入啊. 首先需要排一下序. 代码如下: #include <iostream> #include

POJ 2778 AC自动机+矩阵幂 不错的题

http://poj.org/problem?id=2778 有空再重新做下,对状态图的理解很重要 题解: http://blog.csdn.net/morgan_xww/article/details/7834801 另外做了矩阵幂的模板: //ac.sz是矩阵的大小 void mulmtr(long long x[MAXNODE][MAXNODE],long long y[MAXNODE][MAXNODE])//y=x*y { ll tmp[MAXNODE][MAXNODE]; for(in

2012长春站B题 zoj 3656 并查集

好像大神都用的是2-sat,其实我也有想过.因为我碰到过的判断yes or no的题目就那么几种(2-sat,并查集,搜索,博弈),(因为本人比较水,所以就碰到了这几种,看来以后还是要多做体检积累经验:)),但是比赛的时候还是用了并查集,下面是我的并查集解法: 把b[][]数组上的每个位拆开成两个点i和i',(不超过32位),另外新加两个点0和1,如果确定某点i对应的是0,则i与0点合并,i'点与1点合并:如果确定某点i对应的是1,则i与1合并,i'与0合并:如果确定两点i和j对应的位是相反的数

zoj 3827(牡丹江现场赛I题)

ZOJ Problem Set - 3827 Information Entropy Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge Information Theory is one of the most popular courses in Marjar University. In this course, there is an important chapter about informatio

ZOJ 3798 Abs Problem(规律题)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3798 Abs Problem Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge Alice and Bob is playing a game, and this time the game is all about the absolute value! Alice has

ZOJ Monthly, June 2014 月赛BCDEFGH题题解

比赛链接:点击打开链接 上来先搞了f.c,,然后发现状态不正确,一下午都是脑洞大开,, 无脑wa,无脑ce...一样的错犯2次.. 硬着头皮搞了几发,最后20分钟码了一下G,不知道为什么把1直接当成不能加油的站就会wa..太弱.. 唔···太懒第二天才发题解.. B:Gears 并查集 题解:点击打开链接 C:Consecutive Blocks 离散化一下然后模拟 题解:点击打开链接 D:An Easy Game 设dp[i][j]为前i个位置已经匹配了j个位置的方法数. #include <

ZOJ - 3890 Wumpus(BFS基础题)

Wumpus Time Limit: 2 Seconds      Memory Limit: 65536 KB One day Leon finds a very classic game called Wumpus.The game is as follow. Once an agent fell into a cave. The legend said that in this cave lived a kind of monster called Wumpus, and there we

zoj 3827 Information Entropy 【水题】

Information Entropy Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge Information Theory is one of the most popular courses in Marjar University. In this course, there is an important chapter about information entropy. Entropy is t

dp的两个不错的题

Keeping track of all the cows can be a tricky task so Farmer John has installed a system to automate it. He has installed on each cow an electronic ID tag that the system will read as the cows pass by a scanner. Each ID tag's contents are currently a