开关灯问题

设 $G=(V,E)$ 是一个有限连通图,在每个顶点 $v\in V$ 处放置有一盏灯和一个开关,按下开关以后会改变 $v$ 以及与 $v$ 相邻顶点处的灯的状态。开始时所有灯都是亮的,问能否经过有限次操作把所有灯都熄灭?

答案是肯定的,对任何连通的有限图 $G$ 总是可以办到的。

我们可以假定 $G$ 是简单图(任何两个顶点之间之多只有一条边),这对讨论没有影响。

记 $N[v]$ 为顶点 $v$ 以及与 $v$ 相邻的顶点组成的集合。如果能够证明下面的定理:

定理:存在顶点集 $V$ 的子集 $S$ 使得对任何 $v\in V$,$|S\cap N[v]|$ 都是奇数。

假设存在定理中所述的集合 $S$,那么只要把 $S$ 中的顶点处的开关分别按下一次即可,这样每盏灯都被改变了奇数次状态,从而都熄灭了。

定理的证明:设 $V=\{v_1,\ldots,v_n\}$,对 $V$ 的子集 $S$,定义集合 $S$ 的示性向量 \[1_S=(a_1,\cdots,a_n)\] 为:若 $v_i\in S$ 则 $a_i=1$,否则 $a_i=0$。如果 $T$ 是 $V$ 的另一个子集,$T$ 的示性向量为 \[1_T=(b_1,\cdots,b_n),\]那么 $1_S$ 和 $1_T$ 的内积为

\[1_S\cdot 1_T=\sum_{i=1}^n a_ib_i=|S\cap T|.\]

其中 $|S\cap T|$ 为 $S$ 和 $T$ 的交集的元素个数。

如果我们的运算是在有限域 $\mathbb{F}_2$ 上进行的,那么 $1_S\cdot1_T=1$ 当且仅当 $|S\cap T|$ 为奇数。从现在起,我们都在 $\mathbb{F}_2$ 上考虑问题。

上面这些分析虽然很简单,但却是我们证明的关键。

现在设 $1_{v_1},\cdots,1_{v_n}$ 分别是集合 $N[v_1],\cdots,N[v_n]$ 的示性向量,把它们作为列向量依次排列为矩阵 $A$:

\[A=(1_{v_1}^T,\cdots,1_{v_n}^T).\]

现在我们还不知道应该怎样选取集合 $S$,但是根据前面的叙述我们知道 $|S\cap N[v]|$ 对每个 $v$ 都是奇数这个条件等价于(注意是二元域上的运算)\[1_S A=(1,1,\cdots,1).\]

因此我们只要证明向量 $p=(1,1,\cdots,1)$ 可以被矩阵 $A$ 的行向量线性表出即可。

记 $W$ 为 $A$ 的行向量生成的线性空间,$W^\bot$ 为 $W$ 在 $\mathbb{F}_2^n$ 中的正交补空间,$W$ 和 $W^\bot$ 满足下面的关系:

\[\dim W+\dim W^\bot=n,\quad (W^\bot)^\bot=W.\]

所以要证明 $p\in W$,只要证明 $p$ 和 $W^\bot$ 正交即可。然而 $W^\bot=\ker A$,因此只要证明对任意行向量 $x\in\mathbb{F}_2^n$,若 $Ax^T=0$,则 $(x,p)=0$。或者等价地说,若 $(x,p)\ne0$,则 $Ax^T\ne0$。

$(x,p)\ne0$ 说明 $x$ 的分量中有奇数个 1,$Ax^T$ 是 $A$ 的一些行向量的和,这些行向量与 $x$ 中的那些 1 相对应,因此我们需要说明 $A$ 的任何奇数个行向量的和不会是 0。

若不然,不妨假设 $A$ 的前 $r$ 行之和为 0,这里 $r$ 是一个奇数。考虑由顶点 $v_1,\cdots,v_r$ 以及它们之间的边组成的子图 $H$,于是 $H$ 的每个顶点的度数是奇数(想一想,为什么?)。然而\[\sum_{i=1}^r \deg v_i=2|E(H)|.\]奇数个奇数的和等于偶数,这不可能,这就完成了证明。

时间: 2024-10-12 16:48:46

开关灯问题的相关文章

bzoj1230 [Usaco2008 Nov]lites 开关灯

1230: [Usaco2008 Nov]lites 开关灯 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1615  Solved: 847[Submit][Status][Discuss] Description Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶牛们思维敏捷. 其中一个大型玩具是牛栏中的灯. N (2 <= N <= 100,000) 头奶牛中的每一头被连续的编号为1..N, 站在一个彩色的灯下面.刚到傍晚的时候

开关灯

问题: 开灯问题,有n盏灯,编号为1~n.第一个人把所有灯都打开,第二个人按下所有编号为2的倍数的开关(这些灯将被关掉),第三个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),以此类推.一共有k个人,问最后有哪些灯开着?输入n和k,输出开着的灯的编号.(k<n<1000) 分析: 用数组来存储灯的状态,判断灯是否开着. 代码: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <s

1230: [Usaco2008 Nov]lites 开关灯

1230: [Usaco2008 Nov]lites 开关灯 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1162  Solved: 589[Submit][Status] Description Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶牛们思维敏捷. 其中一个大型玩具是牛栏中的灯. N (2 <= N <= 100,000) 头奶牛中的每一头被连续的编号为1..N, 站在一个彩色的灯下面.刚到傍晚的时候, 所有的灯都是关

AC日记——开关灯 codevs 1690

开关灯 思路: 线段树: bool懒标记维护: 更新区间时是区间总值减去当前值: 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 100005 struct TreeNodeType { int l,r,dis,lit,mid,flag; }; struct TreeNo

开关灯 ToggleButton

开关灯 ToggleButton textOn:对应true的时候:textOff:对应false的时候:给toggleButton设置监听器toggleButton.setOnCheckChangeListener(listener);(有三种方式)isChecked?R.drawable.On:R.drawbale.Off(三目运算符)

BZOJ 1230: [Usaco2008 Nov]lites 开关灯( 线段树 )

线段树.. --------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; ++i ) #define clr( x

Code[VS]1690 开关灯 题解

Code[VS]1690 开关灯 题解  时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description: YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N) 输入描述 Input

【codevs1690】开关灯 线段树 区间修改+区间求和(标记)

[codevs1690]开关灯 2014年2月15日4930 题目描述 Description YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N) 输入描述 Input Description 第 1 行: 用空格隔开的两个整数N和M 第

初识安卓小程序(开关灯——单选多选按钮控制)

如图: 点击单选按钮"开灯",多选按钮就会显示"关灯"且方块里有对勾:反之,点多选按钮,单选按钮也自动改变. 首先,先创建一个安卓项目(我的版本是4.4.2的),名字为"bulb",把两张图片:开灯与关灯状态的图片放入"drawable-"随意一个文件夹下 然后在res文件夹下找到layout文件夹,找到activity_main.xml或fragment_main.xml,在里面输入或拖拽按钮 <RelativeLay

线段树--codevs 1690 开关灯

codevs 1690 开关灯 USACO 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N) 输入描述 Input