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 }