bzoj1770 [Usaco2009 Nov]lights 燈
[Usaco2009 Nov]lights 燈
Time Limit: 10 Sec Memory Limit: 64 MB
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
輸入細節:
一共有五盞燈。燈1、燈4和燈5都連接著燈2和燈3。
Sample Output
3
輸出細節:
按下在燈1、燈4和燈5上面的開關。
scarlyw大佬教我语文,教我读题。。。。
智障题目啊,繁体字真的差评,直接读错了。。。。。
\(x_i\)表示第i个灯泡被按的次数。
\(x_1\ xor\ x_2\ xor\ x_3 = 1\)
按这样就直接列完方程啦。。。。
显然有自由元。
然后我就智障的直接不管自由元就是最优解,
WA。。。。
o,原来自由元的取值会影响别的元啊。。。。
原来最开始解出的不一定是最终答案啊。。。
暴力dfs
#include<bits/stdc++.h>
using namespace std;
int n, m, x, y, now, ans, cnt;
int coefficient[40][40], a[40];
inline void putit()
{
scanf("%d%d", &n, &m); ans = n;
for(int i = 1; i <= m; ++i){
scanf("%d%d", &x, &y);
coefficient[x][y] = 1; coefficient[y][x] = 1;
}
for(int i = 1; i <= n; ++i) coefficient[i][n + 1] = 1, coefficient[i][i] = 1;
}
inline void gauss()
{
int w;
for(int k = 1; k <= n; ++k){
for(w = k; w <= n; ++w) if(coefficient[w][k]) break;
if(k != w && w <= n) for(int i = 1; i <= n + 1; ++i) swap(coefficient[k][i], coefficient[w][i]);
for(int i = 1; i <= n; ++i)
if(coefficient[i][k] && i != k) for(int j = 1; j <= n + 1; ++j) coefficient[i][j] ^= coefficient[k][j];
}
}
void dfs(int now)
{
if(cnt > ans) return;
if(!now) {ans = min(ans, cnt); return;}
if(coefficient[now][now]){
int t = coefficient[now][n + 1];
for(int i = now + 1; i <= n; ++i) if(coefficient[now][i]) t ^= a[i];
a[now] = t;
if(t) cnt++; dfs(now - 1);
if(t) cnt--;
}
else{
a[now] = 0; dfs(now - 1); cnt++;
a[now] = 1; dfs(now - 1); cnt--;
}
}
int main()
{
putit();
gauss();
dfs(n);
cout << ans;
return 0;
}