传送门
SOL
异或方程组板题
注意两点:
1.如果对于当前项,当前行及以下的系数全为0,则跳过(相当于n+1个方程组解n个未知数),后面一定会有无解或无限解(先判断无解,再无限解)
2.仅有一组解的情况下,可以在中途消完 上面行的系数
如:
inline void gauss(){
for(int k=1;k<=n;++k){
bool f=0;
for(int i=k;i<=n;++i)if(a[i][k]){swap(a[i],a[k]);f=1;break;}
if(!f)continue;
****for(int i=1;i<=n;++i)if(a[i][k]&&k!=i)a[i]^=a[k] /*bitset*/;****
}
}
此题要让选0的尽量多,所以dfs。
CODE
#include<bits/stdc++.h>
#define pf printf
#define sf scanf
using namespace std;
const int maxn=50;
int res,n,m;
bool a[maxn][maxn],ans[maxn];
void dfs(int x,int tot){
if(tot>=res)return;
if(x==0){res=min(tot,res);return;}
if(a[x][x]){
bool now=a[x][n+1];
for(int i=x+1;i<=n;++i)if(a[x][i])now^=ans[i];
ans[x]=now;
dfs(x-1,tot+now);
}
else{
ans[x]=0;dfs(x-1,tot);
ans[x]=1;dfs(x-1,tot+1);
}
}
inline void gauss(){
for(int x=1;x<=n;++x){
bool f=0;
for(int i=x;i<=n;++i){
if(a[i][x]){
for(int j=x;j<=n+1;++j)swap(a[i][j],a[x][j]);
f=1;break;
}
}
if(!f)continue;
for(int i=x+1;i<=n;++i){
if(a[i][x])for(int j=x;j<=n+1;++j)a[i][j]^=a[x][j];
}
}
res=0x7f7f7f7f;
dfs(n,0);
cout<<res;
}
signed main (){
sf("%d%d",&n,&m);
for(int i=1;i<=m;++i){int u,v;sf("%d%d",&u,&v);a[u][v]=a[v][u]=1;}
for(int i=1;i<=n;++i)a[i][n+1]=1,a[i][i]=1;
gauss();
return 0;
}