码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1770: [Usaco2009 Nov]lights 燈 [高斯消元XOR 搜索]

时间:2017-02-18 15:58:31      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:for   pre   tin   pen   set   应该   保存   枚举   n+1   

题意:

经典灯问题,求最少次数


 

本题数据不水,必须要暴搜自由元的取值啦

想了好久

然而我看到网上的程序都没有用记录now的做法,那样做遇到自由元应该可能会丢解吧...?

我的做法是把自由元保存下来,枚举的时候只枚举自由元

但这样没法最优性剪枝了

于是枚举的时候还是从n到1枚举,到i时如果i是主元这时候i的值已经可以算出来了,这样就可以最优性剪枝了

但注意主元i你不能用i这个方程,而要保存pivot[i]为i用了哪个方程

 

然后一个伪贪心策略是自由元先搜0

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bitset>
using namespace std;
const int N=40,INF=1e9;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
int n,m,u,v;
bitset<N> a[N];
int fe[N],now;
void Gauss(){
    now=1;
    for(int i=1;i<=n;i++){
        int j=now;//printf("hi %d %d    %d\n",i,now,a[now][i]==1);
        while(j<=n&&!a[j][i]) j++;
        if(j==n+1) {fe[++fe[0]]=i;continue;}
        if(j!=now) swap(a[now],a[j]);
        for(int j=1;j<=n;j++)
            if(j!=now&&a[j][i]) a[j]^=a[now];
        now++;
    }
}    
int main(){
    freopen("in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=m;i++) u=read(),v=read(),a[u][v]=a[v][u]=1;
    for(int i=1;i<=n;i++) a[i][n+1]=a[i][i]=1;
    Gauss();
    //for(int i=1;i<=n;i++) printf("a %d %d\n",i,a[i][n+1]==1);
    //for(int i=1;i<=fe[0];i++) printf("fe %d %d\n",i,fe[i]);
    int ans=0;
    for(int i=1;i<=now;i++) if(a[i][n+1]) ans++;
    printf("%d",ans);
}

 

BZOJ 1770: [Usaco2009 Nov]lights 燈 [高斯消元XOR 搜索]

标签:for   pre   tin   pen   set   应该   保存   枚举   n+1   

原文地址:http://www.cnblogs.com/candy99/p/6413227.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!