ZOJ 3656 Bit Magic 第37屆ACM/ICPC長春賽區現場賽B題 (2-SAT)


 

Bit Magic

Time Limit: 8 Seconds      Memory Limit: 32768 KB

Yesterday, my teacher taught me about bit operators: and (&), or (|), xor (^). I generated a number table a[N], and wrote a program to calculate the matrix table b[N][N] using three kinds of bit operator. I thought my achievement would get teacher's attention.

The key function is the code showed below.

void calculate(int a[N], int b[N][N]) {
	for (int i = 0; i < N; ++i) {
		for (int j = 0; j < N; ++j) {
			if (i == j) b[i][j] = 0;
			else if (i % 2 == 1 && j % 2 == 1) b[i][j] = a[i] | a[j];
			else if (i % 2 == 0 && j % 2 == 0) b[i][j] = a[i] & a[j];
			else b[i][j] = a[i] ^ a[j];
		}
	}
}

There is no doubt that my teacher raised lots of interests in my work and was surprised to my talented programming skills. After deeply thinking, he came up with another problem: if we have the matrix table b[N][N] at first, can you check whether corresponding number table a[N] exists?

Input

There are multiple test cases.

For each test case, the first line contains an integer N, indicating the size of the matrix. (1 ≤ N ≤ 500).

The next N lines, each line contains N integers, the jth integer in ith line indicating the element b[i][j] of matrix. (0 ≤ b[i][j] ≤ 2 ^ 31 - 1)

Output

For each test case, output "YES" if corresponding number table a[N] exists; otherwise output "NO".

Sample Input

2
0 4
4 0
3
0 1 24
1 0 86
24 86 0

Sample Output

YES
NO


本題很簡單,明顯的2-SAT的模版題。
長春現場賽時一眼就看出了這題是2-SAT。只不過模板寫錯了一點,多加了個分號,導致樣例一直出不來。幸好調試之后發現,
修改一下,交上去1A,爽~~~~此題是做得最順利的了。

現場賽的時候內存真的是無窮大啊,直接做31*500*2=31000個點的2-SAT就AC了。但是比賽結束后在ZOJ上就會MLE了~~~~~
要分開做,做31次的2-SAT就可以了~~~~~~
幸好現場賽沒有發現這個問題~~~給力啊~!!!
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<string.h>
using namespace std;

const int MAXN=1100;//

bool visit[MAXN];
queue<int>q1,q2;
//vector建圖方法很妙
vector<vector<int> >adj; //原圖    //中間一定要加空格把兩個'>'隔開
vector<vector<int> >radj;//逆圖
vector<vector<int> >dag;//縮點后的逆向DAG圖
int n,m,cnt;

int id[MAXN],order[MAXN],ind[MAXN];//強連通分量,訪問順序,入度

void dfs(int u)
{
    visit[u]=true;
    int i,len=adj[u].size();
    for(i=0;i<len;i++)
      if(!visit[adj[u][i]])
        dfs(adj[u][i]);
    order[cnt++]=u;
}
void rdfs(int u)
{
    visit[u]=true;
    id[u]=cnt;
    int i,len=radj[u].size();
    for(i=0;i<len;i++)
      if(!visit[radj[u][i]])
        rdfs(radj[u][i]);
}
void korasaju()
{
    int i;
    memset(visit,false,sizeof(visit));
    for(cnt=0,i=0;i<2*n;i++)
      if(!visit[i])
        dfs(i);
    memset(id,0,sizeof(id));
    memset(visit,false,sizeof(visit));
    for(cnt=0,i=2*n-1;i>=0;i--)
      if(!visit[order[i]])
      {
          cnt++;//這個一定要放前面來
          rdfs(order[i]);
      }
}
bool solvable()
{
    for(int i=0;i<n;i++)
      if(id[2*i]==id[2*i+1])
        return false;
   return true;
}

void add(int x,int y)
{
    adj[x].push_back(y);
    radj[y].push_back(x);
}

int b[600][600];
int bit[33];
int main()
{
    int N;
    bit[0]=1;
    for(int i=1;i<31;i++)bit[i]=2*bit[i-1];
    while(scanf("%d",&N)!=EOF)
    {
        n=N;
        bool flag=true;
        for(int i=0;i<N;i++)
          for(int j=0;j<N;j++)
          {
                scanf("%d",&b[i][j]);
                if(i==j&&b[i][j]!=0)flag=false;
            }
        if(!flag)
        {
            printf("NO\n");
            continue;
        }
        for(int i=0;i<N;i++)
        {
            if(!flag)break;
            for(int j=i+1;j<N;j++)
              if(b[i][j]!=b[j][i])
              {
                    flag=false;
                    break;
                }
        }
        if(!flag)
        {
            printf("NO\n");
            continue;
        }
        for(int k=0;k<31;k++)
        {
            adj.assign(2*n,vector<int>());
            radj.assign(2*n,vector<int>());
            for(int i=0;i<N;i++)
                for(int j=i+1;j<N;j++)
                {
                    if(i%2==1&&j%2==1)
                    {
                        int t1=i;
                        int t2=j;
                        if(b[i][j]&bit[k])
                        {
                            add(2*t1,2*t2+1);
                            add(2*t2,2*t1+1);
                        }
                        else
                        {
                            add(2*t1+1,2*t1);
                            add(2*t2+1,2*t2);
                        }
                    }
                    else if(i%2==0&&j%2==0)
                    {
                        int t1=i;
                        int t2=j;
                        if(b[i][j]&bit[k])
                        {
                            add(2*t1,2*t1+1);
                            add(2*t2,2*t2+1);
                        }
                        else
                        {
                            add(2*t1+1,2*t2);
                            add(2*t2+1,2*t1);
                        }
                    }
                    else
                    {
                        int t1=i;
                        int t2=j;
                        if(b[i][j]&bit[k])
                        {
                            add(2*t1,2*t2+1);
                            add(2*t1+1,2*t2);
                            add(2*t2,2*t1+1);
                            add(2*t2+1,2*t1);
                        }
                        else
                        {
                            add(2*t1,2*t2);
                            add(2*t1+1,2*t2+1);
                            add(2*t2,2*t1);
                            add(2*t2+1,2*t1+1);
                        }

                    }
                }
            korasaju();
            if(!solvable())
            {
                flag=false;
                break;
            }
        }
        if(flag)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM