Chieh's Blog

Because Of Coding

ZOJ Problem Set - 3656 Bit Magic

Chieh posted @ 2015年1月04日 16:42 in ZOJ , 276 阅读

飞机票: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4879

分析:搞了一天的2-sat了。。。感觉还是迷迷糊糊真是菜比~~~好了。。。不扯了。。。直接正题:

题意:题意就是给你个矩阵。。。然后求是否有数组满足那段程序的。。。程序自己看啊。。。请点击飞机票。。。这种题怎么变成2-sat。。。烧脑烧力啊。。。,先预处理对角线是否为0和对称点是否一样。。然后只要把每个位单独处理即可~~~。。。坦白地说:对于矩阵的一个元素b[i][j]。。。如果i%2==0&&j%2==0则a[i]&a[j]=b[i][j]。。。这里就可以用到前面文章的内容了。。。就是说a[i]的第k为&a[j]的第k位=b[i][j]的第k位(注:2进制下)然后运用前面文章的信息。不妨设当前点i为1则是i*2,为0则是i*2+1那么就可以建图了

AND 结果为1:建边 x*2+1->x*2,y*2+1->y*2 (两个数必须全为1)

AND 结果为0:建边 y*2->x*2+1,x*2->y*2+1 (两个数至少有一个为0)

OR 结果为1:建边 x*2+1->y*2,2*y+1->x*2 (两个数至少有一个为1)

OR 结果为0:建边 x*2->x*2+1,y*2->y*2+1 (两个数必须全为0)

XOR 结果为1:建边 x*2->y*2+1,y*2->x*2+1,y*2+1->x*2,x*2+1->y*2 (两个数必须不同)

XOR 结果为0:建边 x*2->y*2,y*2->x*2,x*2+1->y*2+1,y*2+1->x*2+1 (两个数必须相同)

这样要处理最多30次。。。因为b[i][j]有范围限制,然后每一次都跑一遍。。。只要有不符合就直接啪啦:NO,如果都想。。YES!啪啪啪~但是速度不快啊。。。不过AC还是轻轻松松的~~~

/*
Author:Chieh
Grow up happy
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define LL long long
using namespace std;
const int maxn=1234;
vector<int> V[maxn];
int ai[567][567];
int n;
void init()
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            scanf("%d",&ai[i][j]);
        }
    }

}
bool instack[maxn];
int dfn[maxn],low[maxn],sta[maxn],belong[maxn],indexx,scnt,cntnum;
void tarjan(int u)
{
    dfn[u]=low[u]=indexx++;
    instack[u]=1;
    sta[++scnt]=u;
    for(int i=0; i<V[u].size(); i++)
    {

        int v=V[u][i];
        if(dfn[v]==-1)
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v])low[u]=min(dfn[v],low[u]);
    }
    if(dfn[u]==low[u])
    {
        for(int v=-1; v!=u; scnt--)
        {
            v=sta[scnt];
            instack[v]=0;
            belong[v]=cntnum;
        }
        cntnum++;
    }
}
void play()
{
    for(int i=0; i<n; i++)
    {
        if(ai[i][i]!=0)
        {
            printf("NO\n");
            return;
        }
    }
    int MAX=0;
    for(int i=0; i<n; i++)
    {
        for(int j=i+1; j<n; j++)
        {   MAX=max(MAX,ai[i][j]);
            if(ai[i][j]!=ai[j][i])
            {
                printf("NO\n");
                return;
            }
        }
    }
    int o=(1<<30);
    while(o>MAX){
        o=o>>1;
    }
    for(int i=1; i<=100; i++)
    {
        if(o==0)break;
        for(int j=0; j<2*n; j++)V[j].clear();
        bool ju=0;
        for(int j=0; j<n; j++)
        {
            for(int k=0; k<n; k++)
            {
                if(j==k)continue;
                int u=(j)*2;
                int v=(k)*2;
                int c=0;
                if(ai[j][k]-o>=0)
                {
                    ju=1;
                    ai[j][k]-=o;
                    c=1;
                }
                if(j%2==0&&k%2==0)
                {
                    if(c==0)
                    {
                        V[u].push_back(v^1);
                        V[v].push_back(u^1);
                    }
                    else
                    {
                        V[u^1].push_back(u);
                        V[v^1].push_back(v);
                    }
                }
                else if(j%2==1&&k%2==1)
                {
                    if(c==0)
                    {
                        V[u].push_back(u^1);
                        V[v].push_back(v^1);
                    }
                    else
                    {
                        V[u^1].push_back(v);
                        V[v^1].push_back(u);
                    }
                }
                else
                {
                    if(c==0)
                    {
                        V[u].push_back(v);
                        V[v].push_back(u);
                        V[u^1].push_back(v^1);
                        V[v^1].push_back(u^1);
                    }
                    else
                    {
                        V[u].push_back(v^1);
                        V[v].push_back(u^1);
                        V[v^1].push_back(u);
                        V[u^1].push_back(v);
                    }
                }
            }
        }
        o=o>>1;
        if(!ju)
        {
            continue;
        }
        indexx=cntnum=0;
        scnt=-1;
        memset(dfn,-1,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        for(int j=0; j<2*n; j++)
        {
            if(dfn[j]==-1)tarjan(j);
        }
        for(int j=0; j<n; j++)
        {
            if(belong[j*2]==belong[j*2+1])
            {
                printf("NO\n");
                return;
            }
        }
    }
    printf("YES\n");
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        init();
        play();
    }
    //  cout << "Hello world!" << endl;
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter