zoukankan      html  css  js  c++  java
  • 【高斯消元】BZOJ 1770: [Usaco2009 Nov]lights 燈


     

    Description

      貝希和她的閨密們在她們的牛棚中玩遊戲。但是天不從人願,突然,牛棚的電源跳閘了,所有的燈都被關閉了。貝希是一個很膽小的女生,在伸手不見拇指的無盡的黑暗中,她感到驚恐,痛苦與絕望。她希望您能夠幫幫她,把所有的燈都給重新開起來!她才能繼續快樂地跟她的閨密們繼續玩遊戲! 牛棚中一共有N(1 <= N <= 35)盞燈,編號為1到N。這些燈被置於一個非常複雜的網絡之中。有M(1 <= M <= 595)條很神奇的無向邊,每條邊連接兩盞燈。 每盞燈上面都帶有一個開關。當按下某一盞燈的開關的時候,這盞燈本身,還有所有有邊連向這盞燈的燈的狀態都會被改變。狀態改變指的是:當一盞燈是開著的時候,這盞燈被關掉;當一盞燈是關著的時候,這盞燈被打開。 問最少要按下多少個開關,才能把所有的燈都給重新打開。 數據保證至少有一種按開關的方案,使得所有的燈都被重新打開。

    Input

      *第一行:兩個空格隔開的整數:N和M。

      *第二到第M+1行:每一行有兩個由空格隔開的整數,表示兩盞燈被一條無向邊連接在一起。 沒有一條邊會出現兩次。

    Output

      第一行:一個單獨的整數,表示要把所有的燈都打開時,最少需要按下的開關的數目。


      其实是和POJ1222差不多的一题。

      但是这题有一些解是自由的(不管是什么都不影响解)。

      所以我们高斯消元后bfs。

      枚举自由元的情况(按和不按),更新最优解。

      

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 int ga[100][100],cnt=0,ans,s[100],n;
     9 
    10 void guass()
    11 {
    12     for(int i=1;i<=n;i++)
    13     {
    14         int j=i;
    15         while(ga[j][i]==0&&j<=n)j++;
    16         if(j>n)continue;
    17         if(j!=i)
    18         {
    19             for(int k=1;k<=n+1;k++)
    20                 swap(ga[i][k],ga[j][k]);
    21         }
    22         if(!ga[i][i])continue;
    23         for(j=1;j<=n;j++)
    24              if(ga[j][i]&&j!=i)
    25                  for(int k=1;k<=n+1;k++)
    26                      ga[j][k]=ga[j][k]^ga[i][k];
    27     }
    28 }
    29 
    30 void dfs(int x)
    31 {
    32     if(cnt>=ans)return;
    33     if(x==0)
    34     {
    35         ans=min(ans,cnt);
    36         return;
    37     }
    38     if(ga[x][x])
    39     {
    40         int num=ga[x][n+1];
    41         for(int i=x+1;i<=n;i++)
    42             if(ga[x][i])
    43                 num=num^s[i];
    44         s[x]=num;
    45         if(num==1)cnt++;
    46         dfs(x-1);
    47         if(num==1)cnt--;
    48     }
    49     if(!ga[x][x])
    50     {
    51         s[x]=0;dfs(x-1);
    52         s[x]=1;cnt++;dfs(x-1);cnt--;
    53     }
    54 }
    55 
    56 int main()
    57 {
    58     int m,x,y;
    59     scanf("%d%d",&n,&m);
    60     for(int i=1;i<=n;i++)
    61         ga[i][i]=1,ga[i][n+1]=1;
    62     for(int i=1;i<=m;i++)
    63         scanf("%d%d",&x,&y),ga[x][y]=ga[y][x]=1;
    64     guass();
    65     ans=1<<30;dfs(n);
    66     printf("%d",ans);
    67     return 0;
    68 }
    View Code

      忽略函数名字2333。。

  • 相关阅读:
    欢庆入住博客园
    指定线程所运行的CPU核心
    [GNU/Linux MakeFile] 第一章:概述
    [.NET][编程之美][1.1]C# 实现让CPU占用率曲线听你的指挥 – 可指定运行核心
    vmware workstation 7.1 正式版 序列号 注册机
    linux:设置 linux定时运行命令脚本 (crontab详解)
    守护进程(Daemon)
    Linux下定时执行脚本
    二叉树的遍历(转)
    dup,dup2,fcntl,ioctl用法简述
  • 原文地址:https://www.cnblogs.com/tuigou/p/4635502.html
Copyright © 2011-2022 走看看