灯 & 树

这回是两道题一起...

[USACO09NOV]

[中山市选2009]树

题意:给您一些灯,以及一些边。每次改变一盏灯的时候,它相邻的灯也会变。求把灯状态全部转换的最小操作次数。

解:

解异或方程组的经典题。

我们对于灯列一个方程组,如果i对j有影响就令a[j][i] = 1

然后解出上三角矩阵。

解出来a[i][i] = 1的地方就是确定的灯。

0就是可有可无的灯。

然后我们大暴力搜索可有可无的灯。遇到确定的灯就根据已经搜索的那些来确定。

 1 #include <cstdio>
 2 #include <bitset>
 3 #include <algorithm>
 4 const int N = 40;
 5 
 6 int n, p[N], ans = 0x3f3f3f3f;
 7 std::bitset<N> a[N];
 8 
 9 inline void Gauss() {
10     for(int i = 1; i < n; i++) {
11         for(int j = i; j <= n; j++) {
12             if(a[j][i]) {
13                 std::swap(a[i], a[j]);
14                 break;
15             }
16         }
17         if(!a[i][i]) {
18             continue;
19         }
20         for(int j = i + 1; j <= n; j++) {
21             if(a[j][i]) {
22                 a[j] ^= a[i];
23             }
24         }
25     }
26     return;
27 }
28 
29 inline void DFS(int k, int s) {
30     if(s >= ans) {
31         return;
32     }
33     if(k < 1) {
34         ans = std::min(ans, s);
35         return;
36     }
37     if(a[k][k]) {
38         int t = a[k][n + 1];
39         for(int i = k + 1; i <= n; i++) {
40             if(a[k][i]) {
41                 t ^= p[i];
42             }
43         }
44         if(t) { /// need press
45             p[k] = 1;
46             DFS(k - 1, s + 1);
47             p[k] = 0;
48         }
49         else {
50             DFS(k - 1, s);
51         }
52     }
53     else {
54         DFS(k - 1, s);
55         p[k] = 1;
56         DFS(k - 1, s + 1);
57         p[k] = 0;
58     }
59     return;
60 }
61 
62 int main() {
63     int m;
64     scanf("%d%d", &n, &m);
65     for(int i = 1, x, y; i <= m; i++) {
66         scanf("%d%d", &x, &y);
67         a[y].set(x);
68         a[x].set(y);
69     }
70 
71     for(int i = 1; i <= n; i++) {
72         a[i].set(n + 1);
73         a[i].set(i);
74     }
75 
76     Gauss();
77 
78     DFS(n, 0);
79 
80     printf("%d", ans);
81 
82     return 0;
83 }
AC代码

一点思考:

我们能不能把上三角矩阵消成最终的那种结果,然后搜索?这样每次在DFS中确定状态就是O(1)的了。

我们既然都消完了,能不能直接把 ans += a[i][i] & a[i][n + 1] ?

事实证明不行...

随手造了点样例发现过不了...

不禁开始思考a[i][i] = 0的意义来。

比如这个最简单的样例:1和2之间有一条边。

那么消元之后的矩阵是这样的:

1 1 1

0 0 0

这是啥啊.....搞不倒

猜你喜欢

转载自www.cnblogs.com/huyufeifei/p/9415571.html