【bzoj1770/Usaco2009 Nov】lights 燈——折半搜索
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。
1 2
1 3
4 2
3 4
2 5
5 3
輸入細節:
一共有五盞燈。燈1、燈4和燈5都連接著燈2和燈3。
Sample Output
3
輸出細節:
按下在燈1、燈4和燈5上面的開關。
輸出細節:
按下在燈1、燈4和燈5上面的開關。
听说是高斯消元?不会写,留坑待填......
写了折半,大概就是先搜前一半点的状态即其代价,f[i]表示状态i的最小代价;
搜索后一半点的时候代价就是当前状态加上状态补集的代价。
再加个hash判重就可以啦。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 typedef long long LL; 5 const int N=36,mod=9875321; 6 using std::min; 7 int n,m,mni=0x3f3f3f3f,h; 8 int hash[mod],tot=0,an[600000]; 9 struct node{int ne;LL to;}e[600000]; 10 LL all; 11 int read(){ 12 int ans=0,f=1;char c=getchar(); 13 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 14 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 15 return ans*f; 16 } 17 LL f[N]; 18 int Hash(LL x){ 19 int p=x%mod; 20 for(int i=hash[p];i;i=e[i].ne)if(e[i].to==x)return i; 21 e[++tot]=(node){hash[p],x};hash[p]=tot; 22 return tot; 23 } 24 void dfs(int x,LL now,int st,int p){ 25 if(st>mni)return; 26 if(x==h+1){ 27 LL no=now;no>>=1; 28 if(no==all)mni=min(mni,st); 29 if(!p){ 30 int k=Hash(no); 31 if(an[k])an[k]=min(an[k],st); 32 else an[k]=st; 33 } 34 else{ 35 int k=Hash(all-no); 36 if(!an[k])return; 37 mni=min(mni,st+an[k]); 38 } 39 return; 40 } 41 dfs(x+1,now,st,p);dfs(x+1,now^f[x],st+1,p); 42 } 43 int main(){ 44 n=read();m=read();all=(1LL<<n)-1; 45 for(int i=1,a,b;i<=m;i++){ 46 a=read();b=read();f[a]|=(1LL<<b);f[b]|=(1LL<<a); 47 } 48 for(int i=1;i<=n;i++)f[i]|=(1LL<<i); 49 h=n/2;dfs(1,0,0,0);h=n;dfs(n/2+1,0,0,1); 50 printf("%d",mni); 51 return 0; 52 } 53