• BZOJ 1770: [Usaco2009 Nov]lights 燈( 高斯消元 )


    高斯消元解xor方程组...暴搜自由元+最优性剪枝 

    -----------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<bitset>
     
    using namespace std;
     
    const int maxn = 49;
     
    int N, Id[maxn], State[maxn], ans = maxn;
    bitset<maxn> mat[maxn];
     
    void Init() {
    int m;
    scanf("%d%d", &N, &m);
    for(int i = 0; i < N; i++) {
    mat[i].reset();
    mat[i][i] = mat[i][N] = 1;
    }
    while(m--) {
    int u, v;
    scanf("%d%d", &u, &v); u--; v--;
    mat[u][v] = mat[v][u] = 1;
    }
    memset(Id, -1, sizeof Id);
    }
     
    void Work() {
    int k = 0;
    for(int i = 0; i < N; i++) {
    for(int j = k; j < N; j++) if(mat[j][i]) {
    if(j != k)
    swap(mat[j], mat[k]);
    break;
    }
    if(mat[k][i]) {
    for(int j = k; ++j < N; )
    if(mat[j][i]) mat[j] ^= mat[k];
    Id[i] = k++;
    }
    }
    }
     
    void Dfs(int x, int sum) {
    if(sum >= ans)
    return;
    if(x < 0) {
    ans = sum; return;
    }
    if(~Id[x]) {
    State[x] = mat[Id[x]][N];
    for(int i = x; ++i < N; )
    if(mat[Id[x]][i]) State[x] ^= State[i];
    Dfs(x - 1, sum + State[x]);
    } else {
    for(int i = 0; i < 2; i++)
    Dfs(x - 1, sum + (State[x] = i));
    }
    }
     
    int main() {
    Init();
    Work();
    Dfs(N - 1, 0);
    printf("%d ", ans);
    return 0;
    }

    -----------------------------------------------------------------------------

    1770: [Usaco2009 Nov]lights 燈

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 545  Solved: 260
    [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

  • 相关阅读:
    位运算大集合
    一道百度面试题——位运算
    一道Google面试题——基数排序思想
    ubuntu12.04 安装nginx+php+mysql (lnmp)的web服务器环境
    Linux常用命令及Vim使用
    Gcc手册(转)
    C语言标准
    匈牙利游戏(次短路问题)
    高级打字机
    矩阵乘法
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4985270.html
Copyright © 2020-2023  润新知