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上面的開關。
陡然发现这题用的繁体字。。。说呢怎么这么黑。。。
嗯、这题是用异或方程。
初始一个n*(n+1)的矩阵。
第i行表示第i盏灯的情况,其中的第j位表示第j盏灯的状态变化是否会对其产生影响。第n+1列表示最终状态与初始状态的异或值(一开是都为1,因为都是从关到开转变了状态)
然后就是果果的高斯消元,我的做法是对于每个a[i,i]把n行都消过去、、不是倒三角。。。如果有唯一解的话终态是一条对角线加一条“虚线”,即第n+1列。
然后进行深搜。枚举每个多解情况的操作。
理论复杂度是2^n。。。不过这个的状态树枯枝败叶各种多啊。。。随便减下都只剩下差不多个树干。。。。
在每层深搜之前判断当前解是否小于当前最优解,否则退出。。。
原来超时的20ms水过。。。
AC
CODE
program bzoj_1770;
var a:array[1..40,1..40] of longint;
ans,tot,n,m:longint;
//===================================================================
procedure init;
var i,x,y:longint;
begin
readln(n,m);
for i:=1 to n do a[i,i]:=1;
for i:=1 to n do a[i,n+1]:=1;
for i:=1 to m do
begin
readln(x,y);
a[y,x]:=1;
a[x,y]:=1;
end; m:=n+1;
end;
//===================================================================
procedure change(x:longint);
var i,j,tt:longint;
begin
for i:=x+1 to n do
if
a[i,x]<>0 then
begin
for j:=1 to m do
begin
tt:=a[x,j]; a[x,j]:=a[i,j]; a[i,j]:=tt;
end; exit;
end;
end;
//===================================================================
procedure xiaoyuan;
var i,j,k:longint;
begin
for i:=1 to n do
begin
if a[i,i]=0
then change(i);
if a[i,i]=0
then continue;
for j:=1 to
n do
begin
if j=i then continue;
if a[j,i]=0 then continue;
for k:=i to m do
a[j,k]:=a[j,k] xor a[i,k];
end;
end;
end;
//===================================================================
procedure dfs(now:longint);
var i:longint;
begin
if tot>ans then exit;
//加了这一句就过了、、
if now=0 then
begin
if tot
exit;
end;
if a[now,now]=1 then
begin
if
a[now,m]=1 then inc(tot);
dfs(now-1);
if
a[now,m]=1 then dec(tot);
end else
begin
if
a[now,m]=1 then exit;
dfs(now-1);
for i:=now-1
downto 1 do
if a[i,now]=1 then a[i,m]:=a[i,m] xor 1;
inc(tot);
dfs(now-1); dec(tot);
for i:=now-1
downto 1 do
if a[i,now]=1 then a[i,m]:=a[i,m] xor 1;
end;
end;
//===================================================================
begin
assign(input,'1.in'); reset(input);
init;
xiaoyuan;
ans:=maxlongint;
tot:=0; dfs(n);
writeln(ans);
end.