HDU 4421 Bit Magic(2-SAT) 2012Changchun Onsite

【题意】

给定n个数a0,,,an-1,它按照以下方式生成b[][]:

现给定b[][],求A是否存在。

 

【分析】

1、只涉及位运算,可对每一个二进制位考虑。

2、对某个二进制位,ai的值要么为0,要么为1。再根据bij的值,找出ai和aj的关系。做一个2-sat可解。

【建图】

1、建图详见代码。注意如果第i个数必须为0,加边(i1->i0)。

2、tarjan缩点求解。

【Mark】

注意原数组坐标从0开始,WA 1发。

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <ctime>
  6 #include <cassert>
  7 #include <iostream>
  8 #include <sstream>
  9 #include <fstream>
 10 #include <map>
 11 #include <set>
 12 #include <vector>
 13 #include <queue>
 14 #include <algorithm>
 15 #include <iomanip>
 16 using namespace std;
 17 
 18 #define abs(x) ((x)>=0?(x):-(x))
 19 #define i64 long long
 20 #define u32 unsigned int
 21 #define u64 unsigned long long
 22 #define clr(x,y) memset(x,y,sizeof(x))
 23 #define PI acos(-1.0)
 24 #define sqr(x) ((x)*(x))
 25 #define maxn 2005
 26 #define maxm 2000005
 27 struct node
 28 {
 29   int v,next;
 30 };
 31 node e[maxm];
 32 int cnt ;
 33 int head[maxn];
 34 int col[maxn];
 35 bool instack[maxn];
 36 int st[maxn],top;
 37 int scnt;
 38 int dep;
 39 int dfn[maxn],low[maxn];
 40 void init()
 41 {
 42   cnt = 0;
 43   memset(head,-1,sizeof(head));
 44   return ;
 45 }
 46 void add(int u ,int v )
 47 {
 48   e[cnt].v = v ;
 49   e[cnt].next = head[u];
 50   head[u] = cnt ++ ;
 51 }
 52 int n ;
 53 void tarjan(int u)
 54 {
 55   int v,x;
 56   dfn[u] = low[u] = cnt ++ ;
 57   st[++top] = u;
 58   instack[u] = 1 ;
 59   for(int i = head[u] ; i!= -1; i = e[i].next)
 60   {
 61     v = e[i].v;
 62     if(dfn[v] == -1)
 63     {
 64       tarjan(v);
 65       low[u] = min(low[u],low[v]);
 66     }
 67     else if(instack[v] ) low[u] = min(low[u],dfn[v]);
 68   }
 69   if(dfn[u] == low[u] )
 70   {
 71     do
 72     {
 73       x = st[top -- ];
 74       instack[x] = 0;
 75       col[x] = scnt;
 76     }while(x != u);
 77     scnt ++ ;
 78   }
 79 }
 80 int b[505][505];
 81 bool work(int k)
 82 {
 83   int val ;
 84   // build graph
 85   init();
 86   for(int i = 1 ;i <= n ; i ++ )
 87   {
 88     for(int j = 1 ;j <= n ; j ++ )
 89     {
 90       if(i == j)
 91       {
 92         if(b[i][j] != 0 ) return false;
 93       }
 94       else
 95       {
 96         val = (b[i][j] >> k ) & 1 ;
 97         if(i % 2 == 0 && j %2 == 0 )
 98         {
 99           if(val == 0  )
100           {
101             add(i+n,i);
102             add(j+n,j);
103           }
104           else
105           {
106               add(i,j+n);
107               add(j,i+n);
108           }
109         }
110         else if(i % 2 == 1 && j % 2 == 1  )
111         {
112           if(val == 0)
113           {
114               add(i+n,j);
115               add(j+n,i);
116           }
117           else
118           {
119             add(i,i+n);
120             add(j,j+n);
121           }
122         }
123         else
124         {
125           if(val == 0 )
126           {
127               add(i,j);
128               add(j,i);
129               add(i+n,j+n);
130               add(j+n,i+n);
131           }
132           else
133           {
134               add(i+n,j);
135               add(j,i+n);
136               add(j+n,i);
137               add(i,j+n);
138           }
139         }
140       }
141     }
142   }
143   // tarjan
144   dep = 0 ;
145   memset(dfn,-1,sizeof(dfn));
146   memset(instack,0,sizeof(instack));
147   top = 0 ;
148   scnt = 0 ;
149   for(int i = 1 ; i <= n * 2 ; i++  )
150   {
151     if(dfn[i] == -1)
152      tarjan(i);
153   }
154   bool flag;
155   flag = true;
156   for(int i = 1 ;i <= n ; i ++ )
157   {
158     if(col[i] == col[i+n])
159     {
160       flag = false;
161       break;
162     }
163   }
164   return flag;
165 }
166 int main()
167 {
168   while(scanf("%d",&n)!=EOF)
169   {
170     for(int i = 1; i <= n ; i ++ )
171     {
172       for(int j = 1; j <= n ; j ++ )
173       {
174         scanf("%d",&b[i][j]);
175       }
176     }
177     bool flag;
178     flag = true;
179     for(int i = 0 ;i < 32 ;i ++ )
180     {
181       flag = flag & work(i);
182       if(!flag ) break;
183     }
184     if(flag)
185       printf("YES\n");
186     else printf("NO\n");
187   }
188     return 0;
189 }
hdu4421

 

 

转载于:https://www.cnblogs.com/wangsouc/articles/3302538.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值