JZOJ1321 灯

Description

  贝希和她的闺密们在她们的牛棚中玩游戏。但是天不从人愿,突然,牛棚的电源跳闸了,所有的灯都被关闭了。贝希是一个很胆小的女生,在伸手不见拇指的无尽的黑暗中,她感到惊恐,痛苦与绝望。她希望您能够帮帮她,把所有的灯都给重新开起来!她才能继续快乐地跟她的闺密们继续玩游戏!
  牛棚中一共有N(1 <= N <= 35)盏灯,编号为1到N。这些灯被置于一个非常复杂的网络之中。有M(1 <= M <= 595)条很神奇的无向边,每条边连接两盏灯。
  每盏灯上面都带有一个开关。当按下某一盏灯的开关的时候,这盏灯本身,还有所有有边连向这盏灯的灯的状态都会被改变。状态改变指的是:当一盏灯是开着的时候,这盏灯被关掉;当一盏灯是关着的时候,这盏灯被打开。
  问最少要按下多少个开关,才能把所有的灯都给重新打开。
  数据保证至少有一种按开关的方案,使得所有的灯都被重新打开。

Input

  第一行:两个空格隔开的整数:N和M。

  第二到第M+1行:每一行有两个由空格隔开的整数,表示两盏灯被一条无向边连接在一起。没有一条边会出现两次。

Output

  第一行:一个单独的整数,表示要把所有的灯都打开时,最少需要按下的开关的数目。

Sample Input

5 6
1 2
1 3
4 2
3 4
2 5
5 3

Sample Output

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

 

posted @ 2018-08-25 08:48  kasiruto  阅读(164)  评论(0编辑  收藏  举报