Description
贝希和她的闺密们在她们的牛棚中玩游戏。但是天不从人愿,突然,牛棚的电源跳闸了,所有的灯都被关闭了。贝希是一个很胆小的女生,在伸手不见拇指的无尽的黑暗中,她感到惊恐,痛苦与绝望。她希望您能够帮帮她,把所有的灯都给重新开起来!她才能继续快乐地跟她的闺密们继续玩游戏!
牛棚中一共有N(1 <= N <= 35)盏灯,编号为1到N。这些灯被置于一个非常复杂的网络之中。有M(1 <= M <= 595)条很神奇的无向边,每条边连接两盏灯。
每盏灯上面都带有一个开关。当按下某一盏灯的开关的时候,这盏灯本身,还有所有有边连向这盏灯的灯的状态都会被改变。状态改变指的是:当一盏灯是开着的时候,这盏灯被关掉;当一盏灯是关着的时候,这盏灯被打开。
问最少要按下多少个开关,才能把所有的灯都给重新打开。
数据保证至少有一种按开关的方案,使得所有的灯都被重新打开。
牛棚中一共有N(1 <= N <= 35)盏灯,编号为1到N。这些灯被置于一个非常复杂的网络之中。有M(1 <= M <= 595)条很神奇的无向边,每条边连接两盏灯。
每盏灯上面都带有一个开关。当按下某一盏灯的开关的时候,这盏灯本身,还有所有有边连向这盏灯的灯的状态都会被改变。状态改变指的是:当一盏灯是开着的时候,这盏灯被关掉;当一盏灯是关着的时候,这盏灯被打开。
问最少要按下多少个开关,才能把所有的灯都给重新打开。
数据保证至少有一种按开关的方案,使得所有的灯都被重新打开。
Input
第一行:两个空格隔开的整数:N和M。
第二到第M+1行:每一行有两个由空格隔开的整数,表示两盏灯被一条无向边连接在一起。没有一条边会出现两次。
第二到第M+1行:每一行有两个由空格隔开的整数,表示两盏灯被一条无向边连接在一起。没有一条边会出现两次。
Output
第一行:一个单独的整数,表示要把所有的灯都打开时,最少需要按下的开关的数目。
Solution
这题用折半搜索做,O(2N/2),不会TLE。
有大佬说可以用高斯消元做。
代码
1 const 2 mo=1000009; 3 var 4 n,m,m1,m2,ans:longint; 5 ha,b:array [0..mo] of int64; 6 op,f:array [0..40] of int64; 7 a:array [0..40,0..40] of longint; 8 bo:array [0..40] of boolean; 9 function min(o,p:longint):longint; 10 begin 11 if o<p then exit(o); 12 exit(p); 13 end; 14 15 procedure init; 16 var 17 i,j,x,y:longint; 18 begin 19 op[0]:=1; 20 for i:=1 to 36 do op[i]:=op[i-1]*2; 21 readln(n,m); 22 for i:=1 to m do 23 begin 24 readln(x,y); 25 inc(a[x,0]); a[x,a[x,0]]:=y; 26 inc(a[y,0]); a[y,a[y,0]]:=x; 27 end; 28 for i:=1 to n do 29 begin 30 f[i]:=op[i-1]; 31 for j:=1 to a[i,0] do 32 f[i]:=f[i]+op[a[i,j]-1]; 33 end; 34 end; 35 36 function hash(x:int64):longint; 37 var 38 i:longint; 39 begin 40 i:=x mod mo; 41 while (ha[i]<>0) and (ha[i]<>x) do 42 i:=(i+1) mod mo; 43 exit(i); 44 end; 45 46 procedure dfs1(x:longint); 47 var 48 num:int64; 49 k,tk,i:longint; 50 begin 51 if x>m1 then 52 begin 53 num:=0; tk:=1; 54 for i:=1 to m1 do 55 if bo[i] then 56 begin 57 num:=num xor f[i]; 58 inc(tk); 59 end; 60 k:=hash(num); 61 if ha[k]=0 then 62 begin 63 ha[k]:=num; b[k]:=tk; 64 end else b[k]:=min(b[k],tk); 65 exit; 66 end; 67 bo[x]:=true; dfs1(x+1); 68 bo[x]:=false; dfs1(x+1); 69 end; 70 71 procedure dfs2(x:longint); 72 var 73 num:int64; 74 k,tk,i:longint; 75 begin 76 if x>m2 then 77 begin 78 num:=0; tk:=-1; 79 for i:=m1+1 to m2 do 80 if bo[i] then 81 begin 82 num:=num xor f[i]; 83 inc(tk); 84 end; 85 k:=hash(op[n]-num-1); 86 if ha[k]<>0 then 87 ans:=min(ans,b[k]+tk); 88 exit; 89 end; 90 bo[x]:=true; dfs2(x+1); 91 bo[x]:=false; dfs2(x+1); 92 end; 93 94 begin 95 init; 96 m1:=min(18,n); m2:=n; 97 ans:=maxlongint; 98 dfs1(1); 99 dfs2(m1+1); 100 write(ans); 101 end.