燈 & 樹

這回是兩道題一塊兒...ide

[USACO09NOV]spa

[中山市選2009]樹code

題意:給您一些燈,以及一些邊。每次改變一盞燈的時候,它相鄰的燈也會變。求把燈狀態所有轉換的最小操做次數。blog

解:it

解異或方程組的經典題。io

咱們對於燈列一個方程組,若是i對j有影響就令a[j][i] = 1event

而後解出上三角矩陣。class

解出來a[i][i] = 1的地方就是肯定的燈。cli

0就是無關緊要的燈。sed

而後咱們大暴力搜索無關緊要的燈。遇到肯定的燈就根據已經搜索的那些來肯定。

 

 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

這是啥啊.....搞不倒

相關文章
相關標籤/搜索