【dfs】【高斯消元】【异或方程组】bzoj1770 [Usaco2009 Nov]lights 燈 / bzoj2466 [中山市选2009]树

经典的开关灯问题。

高斯消元后矩阵对角线B[i][i]若是0,则第i个未知数是自由元(S个),它们可以任意取值,而让非自由元顺应它们,得到2S组解。

枚举自由元取0/1,最终得到最优解。

不知为何正着搜不行。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 36
int n,m;
int ans=2147483647;
bool B[N][N+1],x[N],path[N];
void Madoka()
{
    for(int i=1;i<=n;++i)
      {
        int j=i;
        for(;j<=n;++j) if(B[j][i]) break;
        if(j!=n+1)
          {
            swap(B[i],B[j]);
            for(j=1;j<=n;++j)
              if(i!=j&&B[j][i])
                for(int k=1;k<=n+1;++k)
                  B[j][k]^=B[i][k];
          }
      }
}
void dfs(int cur,int now)
{
    if(now>=ans) return;
    if(!cur) {ans=now; return;}
    if(B[cur][cur])
      {
        bool t=B[cur][n+1];
        for(int i=cur+1;i<=n;++i)
          if(B[cur][i]) t^=path[i];
        path[cur]=t;
        dfs(cur-1,now+t);
      }
    else
      {
        path[cur]=0; dfs(cur-1,now);
        path[cur]=1; dfs(cur-1,now+1);
      }
}
int main()
{
    int x,y;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) B[i][n+1]=1,B[i][i]=1;
    for(int i=1;i<=m;++i)
      {
        scanf("%d%d",&x,&y);
        B[x][y]=B[y][x]=1;
      }
    Madoka();
    dfs(n,0);
    printf("%d\n",ans);
    return 0;
}
posted @ 2015-03-26 10:27  AutSky_JadeK  阅读(329)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト