日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JZOJ 1321. 灯

發布時間:2025/3/15 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JZOJ 1321. 灯 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

Sample Output

3

Data Constraint

Hint

【樣例說明】

  一共有五盞燈。燈1、燈4和燈5都連接著燈2和燈3。按下在燈1、燈4和燈5上面的開關。

Solution

  • 這道題看上去無從下手, N35 的范圍令人有些不知所措。

  • 事實上這道題的解法十分巧妙,用到了 折半搜索 的巧法。

  • 分別搜索 217218 兩部分,記錄其中一部分的答案,用哈希表儲存。

  • 處理另一部分時從哈希表中查找,異或出答案,相加即可。

  • 這樣的時間復雜度折半為 2N2 ,可以通過本題。

  • 詳細代碼見下面:(C++選手可以使用 STL 的 Map 庫代替哈希,代碼為注釋部分,簡單卻較慢)

  • 據說 這題可以用高斯消元來做,一盞燈與周圍燈的異或值為 1 表示亮,列出 N 個方程解之。

Code

#include<cstdio> //#include<map> using namespace std; const int N=36,mo=1234321; //map<long long,int>mp; int n,m,m1,m2,ans=N; int a[N][N]; long long p[N],f[N],g[mo],h[mo]; bool bz[N]; inline int read() {int X=0,w=1; char ch=0;while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*w; } inline int min(int a,int b) {return a<b?a:b; } inline int hash(long long x) {int y=x%mo;while(h[y] && h[y]!=x) y=(y+1)%mo;return y; } inline void dfs1(int x) {if(x>m1){long long num=0;int s=1;for(int i=1;i<=m1;i++)if(bz[i]) num^=f[i],s++;int k=hash(num);if(!h[k]) h[k]=num,g[k]=s; elseg[k]=min(g[k],s);/*if(!mp[num]) mp[num]=s; elsemp[num]=min(mp[num],s);*/return;}bz[x]=true;dfs1(x+1);bz[x]=false;dfs1(x+1); } inline void dfs2(int x) {if(x>m2){long long num=0;int s=-1;for(int i=m1+1;i<=m2;i++)if(bz[i]) num^=f[i],s++;int k=hash(p[n]-1-num);if(h[k]) ans=min(ans,g[k]+s);//if(mp[p[n]-1-num]) ans=min(ans,mp[p[n]-1-num]+s);return;}bz[x]=true;dfs2(x+1);bz[x]=false;dfs2(x+1); } int main() {freopen("1!.in","r",stdin);n=read(),m=read();for(int i=p[0]=1;i<=n;i++) p[i]=p[i-1]<<1;for(int i=1;i<=m;i++){int x=read(),y=read();a[x][++a[x][0]]=y;a[y][++a[y][0]]=x;}for(int i=1;i<=n;i++){f[i]=p[i-1];for(int j=1;j<=a[i][0];j++) f[i]+=p[a[i][j]-1];}m1=min(N>>1,m2=n);//mp[0]=1;dfs1(1);dfs2(m1+1);printf("%d",ans);return 0; }

總結

以上是生活随笔為你收集整理的JZOJ 1321. 灯的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。