zoukankan      html  css  js  c++  java
  • BZOJ 1770: [Usaco2009 Nov]lights 燈

    1770: [Usaco2009 Nov]lights 燈

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

    [Submit][Status][Discuss]

    网上的方法大多是高斯消元解异或方程,对于自由元DFS枚举选还是不选;后来看到Monster_Yi神犇和SD_le神犇的双端搜索,觉得也不错。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int MAXN = 105;
     6 
     7 int N, M, G[MAXN][MAXN], ANS, TMP[MAXN];
     8 
     9 void READ(void)
    10 {
    11     scanf("%d%d", &N, &M);
    12     
    13     for (int i = 1; i <= N; ++i)
    14         G[i][i] = G[i][N + 1] = true;
    15     
    16     for (int i = 1, x, y; i <= M; ++i)
    17     {
    18         scanf("%d%d", &x, &y);
    19         G[x][y] = G[y][x] = true; 
    20     }
    21 }
    22 
    23 void GAUSS(void)
    24 {
    25     for (int i = 1, j, k; i <= N; ++i)
    26     {
    27         for (j = i; j <= N && !G[j][i]; ++j);
    28         
    29         if (j <= N)
    30         {
    31             if (i != j)
    32             {
    33                 for (k = 1; k <= N + 1; ++k)
    34                     swap(G[i][k], G[j][k]); 
    35             }
    36             if (G[i][i])
    37             {
    38                 for (j = 1; j <= N; ++j)
    39                     if (i != j && G[j][i])
    40                         for (k = 1; k <= N + 1; ++k)
    41                             G[j][k] ^= G[i][k];
    42             }
    43         }
    44     }
    45 }
    46 
    47 void DFSANS(int t, int cnt)
    48 {
    49     if (cnt >= ANS)
    50         return;
    51     if (t == 0)
    52         ANS = min(ANS, cnt);
    53     else
    54     {
    55         if (G[t][t])
    56         {
    57             TMP[t] = G[t][N + 1];
    58             for (int i = N; i > t; --i)
    59                 if (G[t][i])TMP[t] ^= TMP[i];
    60             DFSANS(t - 1, cnt + TMP[t]);
    61         }
    62         else
    63         {
    64             TMP[t] = 0; DFSANS(t - 1, cnt);
    65             TMP[t] = 1; DFSANS(t - 1, cnt + 1);
    66         }
    67     }
    68 }
    69 
    70 void PUTANS(void)
    71 {
    72     ANS = 2e9;
    73     DFSANS(N, 0);
    74     printf("%d
    ", ANS);
    75 }
    76 
    77 signed main(void)
    78 {
    79     READ();    
    80     GAUSS();
    81     PUTANS();
    82 }
    高斯消元+DFS枚举
     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long LL;
     6 
     7 const int N = 40;
     8 const int M = 2000;
     9 
    10 int n, m;
    11 
    12 int tot;
    13 int hd[N];
    14 int to[M];
    15 int nt[M];
    16 
    17 int ans;
    18 
    19 map<LL, int> MAP;
    20 
    21 void insert(LL bit, int cost)
    22 {
    23     if (MAP.count(bit))
    24         MAP[bit] = min(MAP[bit], cost);
    25     else
    26         MAP[bit] = cost;
    27 }
    28 
    29 void DFS1(int t, LL bit, int cost)
    30 {
    31     if (t > n / 2)
    32     { insert(bit, cost); return; }
    33     
    34     DFS1(t + 1, bit, cost);
    35     
    36     bit ^= (1LL << (t - 1));
    37     
    38     for (int i = hd[t]; ~i; i = nt[i])
    39         bit ^= (1LL << (to[i] - 1));
    40         
    41     DFS1(t + 1, bit, cost + 1);
    42 }
    43 
    44 int query(LL bit)
    45 {
    46     if (MAP.count(bit))
    47         return MAP[bit];
    48     else
    49         return -1;
    50 }
    51 
    52 void DFS2(int t, LL bit, int cost)
    53 {
    54     if (t > n)
    55     {
    56         int ret = query(((1LL << n) - 1) ^ bit);
    57         if (ret != -1)ans = min(ans, cost + ret);
    58         return;
    59     }
    60     
    61     DFS2(t + 1, bit, cost);
    62     
    63     bit ^= (1LL << (t - 1));
    64     
    65     for (int i = hd[t]; ~i; i = nt[i])
    66         bit ^= (1LL << (to[i] - 1));
    67         
    68     DFS2(t + 1, bit, cost + 1);
    69 }
    70 
    71 signed main(void)
    72 {
    73     scanf("%d%d", &n, &m);
    74     
    75     memset(hd, -1, sizeof(hd));
    76     
    77     for (int i = 1; i <= m; ++i)
    78     {
    79         int x, y; scanf("%d%d", &x, &y);
    80         nt[tot] = hd[x]; to[tot] = y; hd[x] = tot++;
    81         nt[tot] = hd[y]; to[tot] = x; hd[y] = tot++;
    82     }
    83     
    84     ans = 2e9;
    85     DFS1(1, 0LL, 0);
    86     DFS2(n / 2 + 1, 0LL, 0);
    87     
    88     printf("%d
    ", ans);
    89 }
    双端搜索

    @Author: YouSiki

  • 相关阅读:
    编程术语英汉对照
    asp.net常用函数
    好的博客地址
    读取项目中的txt文件内容
    Web Service的定义
    ADO.NET在开发中的部分使用方法和技巧
    如何实现文本框焦点自动跳转及通过回车键提交表单
    15位和18位身份证JS校验实例
    PL/SQL 操作数据库常见脚本
    android 隐藏标题栏
  • 原文地址:https://www.cnblogs.com/yousiki/p/6072345.html
Copyright © 2011-2022 走看看