3
Hint
【样例说明】
一共有五盏灯。灯1、灯4和灯5都连接着灯2和灯3。按下在灯1、灯4和灯5上面的开关。
Solution
这题也可以写高斯消元,这里是双向搜索。
先dfs前半部分,用hash储存,再dfs后半部分。
1 #include<cstdio>
2 #define N 1000007
3 using namespace std;
4 int g[N],sum,mi,l,r,b[50][50],n,m;
5 long long t[N],s[40],tt[40];
6 bool e[50],f[50];
7 int min(int x,int y)
8 {
9 if (x>y) return y;
10 return x;
11 }
12 int hash(long long x)
13 {
14 int z=x%N;
15 while (t[z]!=0&&t[z]!=x)
16 z=(z+1)%N;
17 return z;
18 }
19 int dfs(int x)
20 {
21 if (x>l)
22 {
23 int p=0;
24 for (int i=1;i<=n;i++)
25 f[i]=false;
26 for (int i=1;i<=l;i++)
27 if (e[i])
28 {
29 f[i]=not f[i];
30 for (int j=1;j<=b[i][0];j++)
31 f[b[i][j]]=not f[b[i][j]];
32 p++;
33 }
34 long long num=0;
35 for (int i=1;i<=n;i++)
36 if (f[i]) num+=s[i];
37 int k=hash(num);
38 if (t[k]==0) g[k]=p;
39 else g[k]=min(g[k],p);
40 t[k]=num;
41 return 0;
42 }
43 e[x]=true;
44 dfs(x+1);
45 e[x]=false;
46 dfs(x+1);
47 }
48 int dfs1(int x)
49 {
50 if (x>r)
51 {
52 int p=0;
53 for (int i=1;i<=n;i++)
54 f[i]=false;
55 for (int i=l+1;i<=n;i++)
56 if (e[i])
57 {
58 f[i]=not f[i];
59 for (int j=1;j<=b[i][0];j++)
60 f[b[i][j]]=not f[b[i][j]];
61 p++;
62 }
63 long long num=0;
64 for (int i=1;i<=n;i++)
65 if (f[i]) num+=s[i];
66 int k=hash(s[n]*2-1-num);
67 if (t[k]!=0)
68 mi=min(p+g[k],mi);
69 return 0;
70 }
71 e[l+x]=true;
72 dfs1(x+1);
73 e[l+x]=false;
74 dfs1(x+1);
75 }
76 int ss(int x,int z)
77 {
78 if (z==0)
79 {
80 if (x<mi)
81 mi=x;
82 return 0;
83 }
84 if (x>=mi||x>3)
85 return 0;
86 for (int i=1;i<=n;i++)
87 if (tt[i])
88 {
89 tt[i]=false;
90 int zz=z;
91 if (f[i])
92 zz++;
93 else zz--;
94 f[i]=not f[i];
95 for (int j=1;j<=b[i][0];j++)
96 {
97 if (f[b[i][j]])
98 zz++;
99 else zz--;
100 f[b[i][j]]=not f[b[i][j]];
101 }
102 ss(x+1,zz);
103 f[i]=not f[i];
104 for (int j=1;j<=b[i][0];j++)
105 f[b[i][j]]=not f[b[i][j]];
106 tt[i]=true;
107 }
108 }
109 int main()
110 {
111 scanf("%d%d",&n,&m);
112 for (int i=1;i<=m;i++)
113 {
114 int x,y;
115 scanf("%d%d",&x,&y);
116 b[x][++b[x][0]]=y;
117 b[y][++b[y][0]]=x;
118 }
119 l=n/2,r=n-l;
120 s[1]=1;
121 for (int i=1;i<=n;i++)
122 {
123 f[i]=false;
124 tt[i]=true;
125 }
126 mi=0xffffff;
127 ss(0,n);
128 for (int i=2;i<=n;i++)
129 s[i]=s[i-1]*2;
130 if (mi!=0)
131 {
132 dfs(1);
133 dfs1(1);
134 }
135 printf("%d",mi);
136 }
View Code