P2962 [USACO09NOV]灯Lights

P2962 [USACO09NOV]灯Lights

guass消元异或方程组

#include<bits/stdc++.h>
using namespace std;
#define maxn 100
#define sc(x) scanf("%lld",&x);
#define int long long
int A[maxn][maxn];
int x[maxn];
int ans=1000;
int n,m;
void guass()
{
    for(int i=1; i<=n; i++)
    {
        int t=i;
        if(!A[t][t])
        {
            for(int j=i+1; j<=n; j++)
            {
                if(A[j][i])
                {
                    t=j;
                    break;
                }
            }
            swap(A[i],A[t]);
        }
        for(int k=i+1; k<=n; k++)
        {
            if(A[k][i])
            {
                for(int j=1; j<=n+1; j++)
                {
                    A[k][j]^=A[i][j];///消元
                }
            }
        }

    }
}

void dfs(int i,int t)
{
    if(t>ans)return;
    if(i==0){
        ans=min(t,ans);
        return;
    }
    if(A[i][i]){
        x[i]=A[i][n+1];
        for(int j=i+1;j<=n;j++)
        if(A[i][j]){x[i]^=x[j];}
        if(x[i])dfs(i-1,t+1);
        else dfs(i-1,t);
    }else{
      x[i]=0;
      dfs(i-1,t);
      x[i]=1;
      dfs(i-1,t+1);

    }

}
signed main()
{
    sc(n);sc(m);
    int x,y;
    while(m--){
        sc(x);sc(y);
        A[x][y]=A[y][x]=1;
    }
    for(int i=1;i<=n;i++)A[i][i]=A[i][n+1]=1;
    guass();
    dfs(n,0);
    cout<<ans<<'\n';
}

 折半枚举

#include<bits/stdc++.h>
#define LL long long
#define RI register int
using namespace std;
const int INF = 0x7ffffff ;
const int N = 40 ;

inline int read()
{
    int k = 0, f = 1 ;
    char c = getchar() ;
    for( ; !isdigit(c) ; c = getchar())
        if(c == '-') f = -1 ;
    for( ; isdigit(c) ; c = getchar())
        k = k*10 + c-'0' ;
    return k*f ;
}
int n, m, lv, ans = INF ;
LL hh[N] ;
LL tt ;
LL p1[N], bin[N] ;
bool flag ;
map<LL,int>p ;  // 开不下2^35的数组,其实最多只有2^18个状态,所以用map是可以的

void dfs(int now,LL res,int used)
{
    if(now > lv)
    {
        if(res == tt)
        {
            ans = min(ans,used) ;
        }
        else
        {
            if(!flag)
            {
                int t = p[res] ;
                if(!t || used < t) p[res] = used ;
            }
            else
            {
                if(p[tt^res]) ans = min(ans,p[tt^res]+used) ;
            }
        }
        return ;
    }
    dfs(now+1,res^p1[now],used+1) ;
    dfs(now+1,res,used) ; // 选与不选
}

int main()
{
    n = read(), m = read() ;
    bin[0] = 1 ;
    for(int i=1; i<=n; i++) bin[i] = bin[i-1]<<1 ;
    tt = bin[n] - 1 ;
    memset(hh,0,sizeof(hh)) ;
    LL x, y ;
    for(int i=1; i<=m; i++)
    {
        x = read(), y = read() ;
        hh[x] ^= bin[y-1], hh[y] ^= bin[x-1] ;
    }
    for(int i=1; i<=n; i++) hh[i] ^= bin[i-1] ;
    lv = n>>1 ;
    for(int i=1; i<=lv; i++) p1[i] = hh[i] ;
    dfs(1,0,0) ;  // 搜索前一半
    for(int i=1; i<=n-lv; i++) p1[i] = hh[i+lv] ;
    lv = (n+1)>>1 ;
    flag = 1 ; // flag标记在搜索前半段还是后半段
    dfs(1,0,0) ;  // 搜索后一半
    printf("%d",ans) ;
    return 0 ;
}

 

posted @ 2019-08-27 13:58  liulex  阅读(228)  评论(0编辑  收藏  举报