Description
貝希和她的閨密們在她們的牛棚中玩遊戲。但是天不從人願,突然,牛棚的電源跳閘了,所有的燈都被關閉了。貝希是一個很膽小的女生,在伸手不見拇指的無盡的黑暗中,她感到驚恐,痛苦與絕望。她希望您能夠幫幫她,把所有的燈都給重新開起來!她才能繼續快樂地跟她的閨密們繼續玩遊戲! 牛棚中一共有N(1 <= N <= 35)盞燈,編號為1到N。這些燈被置於一個非常複雜的網絡之中。有M(1 <= M <= 595)條很神奇的無向邊,每條邊連接兩盞燈。 每盞燈上面都帶有一個開關。當按下某一盞燈的開關的時候,這盞燈本身,還有所有有邊連向這盞燈的燈的狀態都會被改變。狀態改變指的是:當一盞燈是開著的時候,這盞燈被關掉;當一盞燈是關著的時候,這盞燈被打開。 問最少要按下多少個開關,才能把所有的燈都給重新打開。 數據保證至少有一種按開關的方案,使得所有的燈都被重新打開。
Input
*第一行:兩個空格隔開的整數:N和M。
*第二到第M+1行:每一行有兩個由空格隔開的整數,表示兩盞燈被一條無向邊連接在一起。 沒有一條邊會出現兩次。
Output
第一行:一個單獨的整數,表示要把所有的燈都打開時,最少需要按下的開關的數目。
其实是和POJ1222差不多的一题。
但是这题有一些解是*的(不管是什么都不影响解)。
所以我们高斯消元后bfs。
枚举*元的情况(按和不按),更新最优解。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm> using namespace std; int ga[][],cnt=,ans,s[],n; void guass()
{
for(int i=;i<=n;i++)
{
int j=i;
while(ga[j][i]==&&j<=n)j++;
if(j>n)continue;
if(j!=i)
{
for(int k=;k<=n+;k++)
swap(ga[i][k],ga[j][k]);
}
if(!ga[i][i])continue;
for(j=;j<=n;j++)
if(ga[j][i]&&j!=i)
for(int k=;k<=n+;k++)
ga[j][k]=ga[j][k]^ga[i][k];
}
} void dfs(int x)
{
if(cnt>=ans)return;
if(x==)
{
ans=min(ans,cnt);
return;
}
if(ga[x][x])
{
int num=ga[x][n+];
for(int i=x+;i<=n;i++)
if(ga[x][i])
num=num^s[i];
s[x]=num;
if(num==)cnt++;
dfs(x-);
if(num==)cnt--;
}
if(!ga[x][x])
{
s[x]=;dfs(x-);
s[x]=;cnt++;dfs(x-);cnt--;
}
} int main()
{
int m,x,y;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
ga[i][i]=,ga[i][n+]=;
for(int i=;i<=m;i++)
scanf("%d%d",&x,&y),ga[x][y]=ga[y][x]=;
guass();
ans=<<;dfs(n);
printf("%d",ans);
return ;
}
忽略函数名字2333。。