BZOJ 1770 USACO 2009 Nov Lights 灯 高斯消元异或方程组

24 篇文章 0 订阅
19 篇文章 0 订阅

%%% http://wenku.baidu.com/link?url=Y55O7adUuZ1biB4m_9wdrJhts9KqqLwnMlI25xgxcpUok9Gv5CrRK9kV9Rxci2Eq8DDcfGi6I9gzVQURJv0kywjihAtkkE61mAss8ZO8qOW

对于每盏灯,有方程组xor{X[adj[i]]} = 1。

解异或方程组即可。

可以尝试把ts >= ans 改成ts > ans会发生啥。

(其实就是16ms -> 48ms的区别而已)

然而压位并没有优化时间,毕竟N=35。。。

#include <cstdio>
#define FOR(i,l,r) for (int i=l;i<=r;++i)
int read() {  
    int s = 0, f = 1; char ch = getchar();
    for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
    for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';
    return s * f;
}
long long a[38], tmp;
int n, ans = 2147483647;
bool sta[38];
void dfs(int x, int ts) {
    if (ts >= ans) return;
    if (!x) { ans = ts; return; }
    if (a[x] & (1ll << x)) {
        sta[x] = a[x] & 1ll << n + 1;
        FOR(k,x+1,n) sta[x] ^= (a[x] & 1ll << k ? 1 : 0) & sta[k];
        dfs(x - 1, ts + sta[x]);
    } else {
        sta[x] = 1; dfs(x - 1, ts + sta[x]);
        sta[x] = 0; dfs(x - 1, ts + sta[x]);
    }
}
int main() {
    int m, x, y;
    n = read(); m = read();
    FOR(i,1,n) a[i] |= 1ll << i, a[i] |= 1ll << n + 1;
    FOR(i,1,m) {
        x = read(); y = read();
        a[x] |= 1ll << y; a[y] |= 1ll << x;
    }
    FOR(i,1,n) {
        FOR(j,i,n) if ((a[j] & 1ll << i) > (a[i] & 1ll << i)) tmp = a[i], a[i] = a[j], a[j] = tmp;
        FOR(j,1,n) if (i != j && (a[j] & 1ll << i)) a[j] ^= a[i] & (1ll << 63) - (1ll << i);
    }
    dfs(n, 0);
    printf("%d\n", ans);
    return 0;
}

1770: [Usaco2009 Nov]lights 燈

Time Limit: 10 Sec   Memory Limit: 64 MB
Submit: 606   Solved: 290

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上面的開關。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值