bzoj 1770 [Usaco2009 Nov]lights 燈

1770: [Usaco2009 Nov]lights 燈

Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 888 Solved: 417
[Submit][Status][Discuss]
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上面的開關。
HINT

Source

Gold


【分析】
高斯消元解异或方程组…
然后暴搜自由元状态


【代码】

#include<iostream>
#include<cstring>
#include<cstdio>
#define p(i,j) (i-1)*6+j
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=50;
int x[mxn],a[mxn][mxn],n,m,ans=1e9;
inline void guass()
{
    int i,j,k,x;
    fo(i,1,n)
    {
        fo(k,i+1,n)
          if(a[k][i])
          {
              fo(j,1,n+1) 
                swap(a[k][j],a[i][j]);
              break;
          }
        fo(k,1,n) if(a[k][i] && k!=i)
          fo(j,1,n+1) a[k][j]^=a[i][j];
    }
}
inline void dfs(int v,int now)
{
    int i,j,k;
    if(now>=ans) return;
    if(!v) {ans=now;return;}
    if(a[v][v])
    {
        x[v]=a[v][n+1];
        fo(k,v+1,n) x[v]^=(a[v][k]&x[k]);
        dfs(v-1,now+x[v]);
//      when it all comes to an end , but the world keeps spinning around.
    }
    else
    {
        x[v]=0,dfs(v-1,now);
        x[v]=1,dfs(v-1,now+1);
    }
}
int main()
{
    int i,j,u,v;
    scanf("%d%d",&n,&m);
    fo(i,1,n) a[i][i]=a[i][n+1]=1;
    fo(i,1,m)
      scanf("%d%d",&u,&v),a[u][v]=a[v][u]=1;
    guass(),dfs(n,0);
    printf("%d\n",ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值