题目描述:
给出$n$,$m$,表示有$n$盏灯和$m$条奇怪的电线,按下电线一段的灯后另一端会有影响。
求最少按几次。
题解:
高消解异或方程组,得到一堆自由元后搜索自由元状态,然后不断更新答案。
数据卡贪心好评。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 40; int n,m,hed[N],cnt; struct EG { int to,nxt; }e[N*N]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } int a[N][N]; int fre[N],tl; void gs() { int l1; for(l1=1;l1<=n;l1++) { int tmp = l1; while(tmp<=n&&!a[tmp][l1])tmp++; if(tmp>n)continue; if(tmp!=l1)for(int i=l1;i<=n+1;i++)swap(a[l1][i],a[tmp][i]); for(int i=1;i<=n;i++) if(a[i][l1]&&i!=l1) for(int j=l1;j<=n+1;j++)a[i][j]^=a[l1][j]; } } int ans=0x3f3f3f3f; void dfs(int dep,int now) { if(now>=ans)return ; if(!dep){ans=now;return ;} if(a[dep][dep]) { dfs(dep-1,now+a[dep][n+1]); }else { if(a[dep][n+1])return ; dfs(dep-1,now); for(int j=dep-1;j>=1;j--)a[j][n+1]^=a[j][dep]; dfs(dep-1,now+1); for(int j=dep-1;j>=1;j--)a[j][n+1]^=a[j][dep]; } } int main() { scanf("%d%d",&n,&m); for(int f,t,i=1;i<=m;i++) { scanf("%d%d",&f,&t); ae(f,t),ae(t,f); } for(int i=1;i<=n;i++) { a[i][i]=a[i][n+1]=1; for(int j=hed[i];j;j=e[j].nxt) { int to = e[j].to; a[i][to]^=1; } } gs(); dfs(n,0); printf("%d ",ans); return 0; }