poj 2345 Central heating
Central heating
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 703 | Accepted: 321 |
Description
Winter has come, but at the Ural State University heating is not turned on yet. There's one little problem: the University is heated only if all of the valves are opened. There are some technicians at the University. Each of them is responsible for one or more valves. There may be several technicians responsible for the same valve. When a technician gets an instruction to turn on the heating he goes round all of his valves and turns them. It means that if a valve was opened then he closes it, and if it was closed then he opens it. It is well known that every technician earns his money not in vain so it's impossible to replace any technician by any combination of other technicians.
Your task is to determine who of the technicians is to get an instruction "to turn on the heating" in order to heat all the Ural State University. Note that there are N technicians and N valves at the University (1 <= N <= 250).
Your task is to determine who of the technicians is to get an instruction "to turn on the heating" in order to heat all the Ural State University. Note that there are N technicians and N valves at the University (1 <= N <= 250).
Input
The first line of an input contains the number N. The next N lines contain lists of the valves in charge of each of the technicians. It means that a line number i + 1 contains numbers of the valves that the i-th technician is responsible for. Each list of valves is followed by –1.
Output
An output should contain a list of technicians' numbers sorted in ascending order. If several lists are possible, you should send to an output the shortest one. If it's impossible to turn on the heating at the University, you should write "No solution" .
Sample Input
4 1 2 -1 2 3 4 -1 2 -1 4 -1
Sample Output
1 2 3
题意:
n个人控制n台机器,并且有n个开关,每台机器都可以控制一部分开关的开和闭,并且任何一台机器的功能都不能被其余的机器所取代,最终要将n个开关都打开,问每台机器应该被操作几次
思路:
每个开关最终的结果要么是1(开),要么是0(闭),并且这个结果是由n台机器进行操作后得到,并且有一个事实,机器操作奇数次和操作一次的效果是一样的,操作偶数次和不操作是一样的,所以其实每台机器只有操作或者不操作两种情况。
依据样例做一个解释:设4台机器分别操作x1,x2,x3,x4次,并且最终4个开关都要处于开的状态
对于第一个开关(1,0,0,0)(x1)==1 对于第二个开关(1,1,1,0)(x1)==1 对于第三个开关(0,1,0,0)(x1)==1 对于第四个 (0,1,0,1)(x1)==1
(x2) (x2) (x2) (x2)
(x3) (x3) (x3) (x3)
(x4) (x4) (x4) (x4)
把上述方程合并成矩阵形式,gauss消元求解即可,只是原来的减法要改成异或运算,乘法要改成与运算即可
其中(1,0,0,0),(1,1,1,0),(0,1,0,0),(0,1,0,1)线性无关,意味着一定会有解
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<cstdio> #include<vector> #include<algorithm> #include<cstring> #include<set> #include<string> #include<queue> #include<cmath> #include<bitset> #include<map> using namespace std; #define INF 0x3f3f3f3f const double EPS = 1e-8; const int N_MAX = 250 + 16; typedef long long ll; typedef vector<int>vec; typedef vector<vec>mat; int n; vec gauss(const mat&A,const vec&b) { int n = A.size();//!!!! mat B(n, vec(n + 1)); for (int i = 0; i < n; i++) for (int j = 0; j < n; j++)B[i][j] = A[i][j]; for (int i = 0; i < n; i++)B[i][n] = b[i]; for (int i = 0; i < n;i++) { int pivot = i; for (int j = i; j < n;j++) { if (B[j][i] > B[pivot][i]) {//!!! pivot = j; } } swap(B[i],B[pivot]); if (B[i][i] < EPS)return vec();//无解,当然这题都有解 for (int j = 0; j < n; j++) { if (i != j) { for (int k = i + 1; k <= n; k++) { B[j][k] ^= B[j][i]&B[i][k]; } } } } vec x(n); for (int i = 0; i < n;i++) { x[i] = B[i][n]; } return x; } int main() { while (scanf("%d",&n)!=EOF) { vec b(n); for (int i = 0; i < n;i++) {//预处理 b[i] = 1; } mat A(n, vec(n)); for (int i = 0; i < n; i++) { while (1){ int a; scanf("%d",&a); if (a == -1)break; a--; A[a][i] = 1; } } vec x = gauss(A, b); bool flag = 0; for (int i = 0; i < x.size();i++) { if (x[i]) { if (!flag) { flag = 1; printf("%d",i+1); } else { printf(" %d",i+1); } } } puts(""); } return 0; }