JZOJ 1321. 灯

Description

  贝希和她的闺密们在她们的牛棚中玩游戏。但是天不从人愿,突然,牛棚的电源跳闸了,所有的灯都被关闭了。贝希是一个很胆小的女生,在伸手不见拇指的无尽的黑暗中,她感到惊恐,痛苦与绝望。她希望您能够帮帮她,把所有的灯都给重新开起来!她才能继续快乐地跟她的闺密们继续玩游戏!
  牛棚中一共有N(1 <= N <= 35)盏灯,编号为1到N。这些灯被置于一个非常复杂的网络之中。有M(1 <= M <= 595)条很神奇的无向边,每条边连接两盏灯。
  每盏灯上面都带有一个开关。当按下某一盏灯的开关的时候,这盏灯本身,还有所有有边连向这盏灯的灯的状态都会被改变。状态改变指的是:当一盏灯是开着的时候,这盏灯被关掉;当一盏灯是关着的时候,这盏灯被打开。
  问最少要按下多少个开关,才能把所有的灯都给重新打开。
  数据保证至少有一种按开关的方案,使得所有的灯都被重新打开。
 

Input

  第一行:两个空格隔开的整数:N和M。

  第二到第M+1行:每一行有两个由空格隔开的整数,表示两盏灯被一条无向边连接在一起。没有一条边会出现两次。

Output

  第一行:一个单独的整数,表示要把所有的灯都打开时,最少需要按下的开关的数目。
 

Sample Input

5 6
1 2
1 3
4 2
3 4
2 5
5 3

Sample Output

3
 
做法:高斯消元解异或方程组,或折半搜索都可以过啦。
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #define LL long long
 6 using namespace std;
 7 LL m[60][60];
 8 int n, M, b[60], ans, Ans[60];
 9 
10 void Init()
11 {
12     scanf("%d%d", &n, &M);
13     for (int i = 1; i <= n; i++)
14             m[i][i] = 1, b[i] = 1;
15     for (int i = 1; i <= M; i++)
16     {
17         int u, v;
18         scanf("%d%d", &u, &v);
19         m[u][v] = 1;
20         m[v][u] = 1;
21     }
22 }
23 
24 void Dfs(int dep, int count)
25 {
26     if (count >= ans)    return;
27     if (dep == 0)
28     {
29         if (count < ans)    ans = count;
30         return;
31     }
32     if (m[dep][dep])
33     {
34         bool now = b[dep];
35         for (int i = dep + 1; i <= n; i++)
36             if (m[dep][i])    now ^= Ans[i];
37         Ans[dep] = now;
38         if (Ans[dep])    Dfs(dep - 1, count + 1);
39         else Dfs(dep - 1, count);
40     }
41     else
42     {
43         Ans[dep] = 0;    Dfs(dep - 1, count);
44         Ans[dep] = 1;    Dfs(dep - 1, count + 1);
45         Ans[dep] = 0;
46     }
47 }
48 
49 void Swap(int l, int r)
50 {
51     for (int i = 1; i <= n; i++)
52         swap(m[l][i], m[r][i]);
53     swap(b[l], b[r]);
54 }
55 
56 void Xor(int l, int r)
57 {
58     for (int i = 1; i <= n; i++)
59         m[l][i] ^= m[r][i];
60     b[l] ^= b[r];
61 }
62 
63 void Work()
64 {
65     for (int k = 1; k <= n; k++)
66     {
67         bool flag = 0;
68         for (int i = k; i <= n; i++)
69             if (m[i][k])
70             {
71                 flag = 1;
72                 Swap(i, k);
73                 break;
74             }
75         if (flag == 0)    continue;
76         for (int i = k + 1; i <= n; i++)
77             if (m[i][k])    Xor(i, k);
78     }
79 }
80 
81 int main()
82 {
83     Init();
84     Work();
85     ans = 10000000;
86     Dfs(n, 0);
87     printf("%d", ans);
88 }
高斯消元
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define N 40
 5 #define M 100007
 6 #define LL long long
 7 using namespace std;
 8 int n, m, tot, g[M + 1], ans = M;
 9 LL h[M + 1], Ans, a[N], S[40];
10 
11 void Pre_work()
12 {
13     S[0] = 1;
14     for (int i = 1; i <= 39; i++)    S[i] = S[i - 1] * 2;
15 }
16 
17 void Init()
18 {
19     Pre_work();
20     scanf("%d%d", &n, &m);
21     int u, v;
22     for (int i = 1; i <= n; i++)
23         a[i] |= S[i];
24     for (int i = 1; i <= m; i++)
25     {
26         scanf("%d%d", &u, &v);
27         a[u] |= S[v];
28         a[v] |= S[u];
29     }    
30     Ans = S[n + 1] - 2;    
31 }
32 
33 int Hash(LL x)
34 {
35     int p =    x % M;
36     for (; h[p] != 0 && h[p] != x; p = (p + 1) % M);
37     return p; 
38 }
39 
40 void Dfs(int dep, LL num, int step)
41 {
42     if (dep > tot)
43     {
44         if (num == Ans) ans = min(ans, step);
45         int site = Hash(num);
46         if (!h[site])    h[site] = num, g[site] = step;
47         else g[site] = g[site] < step ? g[site] : step;
48         return;
49     }
50     Dfs(dep + 1, num ^ a[dep], step + 1);
51     Dfs(dep + 1, num, step);
52 }
53 
54 void dfs(int dep, LL num, int step)
55 {
56     if (dep > n)
57     {
58         if (num == Ans) ans = min(ans, step);
59         LL p = Ans ^ num;
60         int site = Hash(p);
61         if (h[site])    ans = min(ans, g[site] + step);
62         return;
63     }
64     dfs(dep + 1, num ^ a[dep], step + 1);
65     dfs(dep + 1, num, step);
66 }
67 
68 int main()
69 {
70     Init();
71     tot = n / 2;
72     Dfs(1, 0, 0);
73     dfs(tot + 1, 0, 0);
74     printf("%d", ans);
75 }
折半搜索
原文地址:https://www.cnblogs.com/traveller-ly/p/9514444.html