The 2012 ACM-ICPC Asia Changchun Regional Contest(problem B)

来源:互联网 发布:js面向对象的特点 编辑:程序博客网 时间:2024/05/16 18:08

zoj题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4879

题意:

已知b数组,问是否 存在a数组满足b数组的要求。

解析:枚举a[i]的每一个二进制位,只有两种情况0或1,因为各个位是相对独立的,所以可以分开考虑31位,每一个是否存在解可以用2-sat来解决。之前也不知2-sat,推荐看看算法合集之《由对称性解2-SAT问题》等想关资料。


参考代码:

#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;#define BUG cout<<"BUG"<<endl;#define clr(arr,v) memset(arr,v,sizeof(arr))typedef long long LL;const int M = 505;const int MAX_M = 1205;int B[M][M],A[M] = {0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912};int h[MAX_M],num[MAX_M*MAX_M],nex[MAX_M*MAX_M],pos;int Low[MAX_M*2],DFN[MAX_M*2],Connect[MAX_M*2],Stack[MAX_M*2],InStack[MAX_M*2],ConnectNum,top,ind;void init(){    ConnectNum = pos = 0;    ind = top = 0;    clr(h,-1);    clr(Low,0);    clr(DFN,0);    clr(InStack,0);}void add(int u,int v){    num[pos] = v;    nex[pos] = h[u];    h[u] = pos++;}void tarjin(int x){    Low[x] = DFN[x] = ++ind;    Stack[++top] = x;    InStack[x] = true;    for(int i = h[x];i != -1;i = nex[i])    {        if(!DFN[ num[i] ])        {            tarjin(num[i]);            Low[x] = min(Low[x],Low[ num[i] ]);        }        else if(InStack[ num[i] ])        {            Low[x] = min(Low[x],DFN[ num[i] ]);        }    }    if(Low[x] == DFN[x])    {        ConnectNum++;        int s;        do{            s = Stack[top--];            Connect[s] = ConnectNum;            InStack[s] = false;        }while(x != s);    }}bool solve(int n){    for(int i = 1;i < 31;++i)    {        init();        for(int j = 0;j < n;++j)        {            for(int k = j+1;k < n;++k)            {                if(j%2 == 0 && k%2 == 0)                {                    if(B[j][k]&A[i])                    {                        add(j*2,j*2+1);                        add(k*2,k*2+1);                    }                    else                    {                        add(j*2+1,k*2);                        add(k*2+1,j*2);                    }                }                else if(j%2 == 1 && k%2 == 1)                {                    if(B[j][k]&A[i])                    {                        add(j*2,k*2+1);                        add(k*2,j*2+1);                    }                    else                    {                        add(j*2+1,j*2);                        add(k*2+1,k*2);                    }                }                else                {                    if(B[j][k]&A[i])                    {                        add(j*2,k*2+1);                        add(k*2,j*2+1);                        add(j*2+1,k*2);                        add(k*2+1,j*2);                    }                    else                    {                        add(j*2,k*2);                        add(k*2+1,j*2+1);                        add(j*2+1,k*2+1);                        add(k*2,j*2);                    }                }            }        }        for(int j = 0;j < n*2;++j)        {            if(!DFN[j]) tarjin(j);        }        for(int j = 0;j < n;++j)        {            if(Connect[j*2] == Connect[j*2+1])            return false;        }    }    return true;}int main(){    int n;    while(cin>>n)    {        bool flag = false;        for(int i = 0;i < n;++i)        {            for(int j = 0;j < n;++j)            {                cin>>B[i][j];                if(i == j && B[i][j]) flag = true;                if(j < i && B[i][j] != B[j][i]) flag = true;            }        }        if((!flag) && solve(n)) cout<<"YES"<<endl;        else cout<<"NO"<<endl;    }    return 0;}


原创粉丝点击