bzoj 2466 异或方程组

 

对于每个灯,我们用一个变量表示其决策,xu=0表示不选,xu=1表示选。因为每个灯最后必须都亮,所以每个等都对应一个异或方程。

解这个异或方程组,有几种情况:

  1、存在唯一解(得到的上三角系数矩阵的主对角线上的元素全部为1)

  2、无解(存在某行系数全为0,但等式右边不为0)

  3、存在v个自由元(即主对角线上有v个0,我们枚举每个自由元的取值,有2v种情况)

我们统计所有合法解的最小的值作为答案。

 

  1 /**************************************************************
  2     Problem: 2466
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:16 ms
  7     Memory:1352 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <iostream>
 13 #define N 100
 14 #define oo 0x3f3f3f3f
 15 using namespace std;
 16  
 17 int n, ans;
 18 int head[N], dest[N<<1], next[N<<1], etot;
 19 int aa[N][N+1], bb[N][N+1], cc[N];
 20 int stk[N], top;
 21  
 22 void init() {
 23     memset( head, 0, sizeof(head) );
 24     etot = 0;
 25     top = 0;
 26     ans = oo;
 27 }
 28 void adde( int u, int v ) {
 29     etot++;
 30     next[etot] = head[u];
 31     dest[etot] = v;
 32     head[u] = etot;
 33 }
 34 void print() {
 35     for( int i=0; i<n; i++ ) {
 36         for( int j=0; j<=n; j++ )
 37             printf( "%d ", aa[i][j] );
 38         printf( "\n" );
 39     }
 40     printf( "\n" );
 41 }
 42 void gauss() {
 43     for( int i=0; i<n; i++ ) {
 44         for( int j=i; j<n; j++ ) {
 45             if( aa[j][i]==1 ) {
 46                 for( int k=i; k<=n; k++ )
 47                     swap( aa[i][k], aa[j][k] );
 48                 break;
 49             }
 50         }
 51         if( aa[i][i]==1 ) {
 52             for( int j=i+1; j<n; j++ ) {
 53                 if( aa[j][i]==1 ) {
 54                     for( int k=i; k<=n; k++ ) 
 55                         aa[j][k] ^= aa[i][k];
 56                 }
 57             }
 58         } else {
 59             stk[top++] = i;
 60         }
 61 //      print();
 62     }
 63 }
 64 int calc() {
 65     memcpy( bb, aa, sizeof(aa) );
 66     int rt = 0;
 67     for( int i=n-1; i>=0; i-- ) {
 68         bool a=bb[i][i], b=bb[i][n];
 69         if( a ) {
 70             if( b ) {
 71                 rt++;
 72                 for( int j=i-1; j>=0; j-- )
 73                     bb[j][n] ^= bb[j][i];
 74             } else {
 75                 //  do nothing
 76             }
 77         } else {
 78             if( b ) {
 79                 return oo;
 80             } else {
 81                 if( cc[i] ) {
 82                     rt++;
 83                     for( int j=i-1; j>=0; j-- )
 84                         bb[j][n] ^= bb[j][i];
 85                 }
 86             }
 87         }
 88     }
 89     return rt;
 90 }
 91 void dfs( int i ) {
 92     if( i==top ) {
 93         int tans = calc();
 94         if( ans>tans ) ans=tans;
 95         return;
 96     }
 97     cc[stk[i]]=0;
 98     dfs(i+1);
 99     cc[stk[i]]=1;
100     dfs(i+1);
101 }
102 int main() {
103     while( scanf("%d",&n)==1 && n!=0 ) {
104         init();
105         for( int t=1,u,v; t<n; t++ ) {
106             scanf( "%d%d", &u, &v );
107             u--, v--;
108             adde(u,v);
109             adde(v,u);
110         }
111         memset( aa, 0, sizeof(aa) );
112         for( int u=0; u<n; u++ ) {
113             aa[u][u] = 1;
114             for( int t=head[u]; t; t=next[t] ) {
115                 int v=dest[t];
116                 aa[v][u] = 1;
117             }
118         }
119         for( int v=0; v<n; v++ )
120             aa[v][n] = 1;
121         gauss();
122         dfs(0);
123         printf( "%d\n", ans );
124     }
125 }
View Code

 

posted @ 2015-05-23 10:59  idy002  阅读(472)  评论(0编辑  收藏  举报