POJ 1977 Odd Loving Bakers

Odd Loving Bakers
Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 1372   Accepted: 429

Description

There is a group of N bakers in the town of Utopia. These bakers hold a monthly celebration in which they award a prize to some of the luckier among themselves. These lucky guys are chosen as follows:

In the beginning there are some chalk marks on some of the bakers' houses. Each baker has a list of his/her favorite bakers. After each celebration each of the winners puts a chalk mark on the house of all the bakers in his/her favorite list. Before each celebration those bakers with an odd number of chalk marks on their house will be chosen as winners. As there will be a great prize for the winners of the t th celebration, you are asked to find the number of its winners.

Input

The first line of the input contains a single integer X (1 <= X <= 11), the number of test cases, followed by the input data for each test case. The input for each test case will be as follows:
The first line of each instance contains two integers n (the number of bakers) and t (the number of the celebration we want the winners of).
1 <= n <= 100
1 <= t <= 1,000,000,000
The next n lines of the instance each describe a baker. In each of these lines first comes the name of the baker (names are lower case strings of no more than 20 characters without spaces), then comes the number of chalk marks initially on the baker's house, then comes the number of bakers in this baker's favorite list, and after that come the names of the bakers in this baker's list.

Output

There should be one line per test case. For each test case write a line containing a single integer, the number of the winners of the t-th celebration.

Sample Input

2
3 2
bessie 2 3 bessie linda mary
mary 1 1 linda
linda 0 1 bessie
2 2	
siavosh 1 2 siavosh mohammad 
mohammad 1 0

Sample Output

2
0

Source

Tehran Sharif 2004 Preliminary

 

/* 首先根据题目输入求出ia[]以及rel[][], ia[i]为1表示baker i初始时的chalk数为奇数,否则为 偶数, rel[i][j] = 1表示baker i 仰慕 baker j,那么第一次庆祝结束后的winner状态为: ia[] * rel[][] + ia[] = ia[] * (rel[][] + I[][]), I为单位矩阵,同理第二次后的状态为: ia[] * (rel[][] + I[][]) ^ 2,所以p次后的winner状态即为ia * (rel[][] + I[][]) ^ n; 所以整个问题就转换为了矩阵的快速幂运算。 矩阵的快速幂运算和求大数幂运算很像: 求res = A ^ p mod k, 先将p转为二进制,然后从低位向高位逐位计算,例如:p = 10110 则A ^ P mod k = {(A ^ 10) mod k) * (A ^ 100) mod k) * (A ^ 10000) mod k},在遍历的时候 可以用一个辅助矩阵expv记录(A ^ (2 ^ i)) mod k,每往上处理一位expv *= expv,如果p的当前位 为1则将res += expv mod k, 最后res即为结果 */ #include <iostream> #include <map> #include <string> #define MAX_N 105 using namespace std; int n, t, indexnum; struct matrix { int m[MAX_N][MAX_N]; }; int ia[MAX_N], res[MAX_N]; matrix rel; map<string, int> mapper; //计算a * b并将结果放在c中 a为s1 * s2矩阵,b为s2 * s3矩阵 matrix mult(const matrix &a, const matrix &b) { matrix res; memset(res.m, 0, sizeof(res.m)); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) for(int k = 0; k < n; k++) res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % 2; return res; } //计算a的p次方并将结果放在a中 matrix pow(matrix a, int p) { matrix temp; int i; memset(temp.m, 0, sizeof(temp.m)); for(i = 0; i < n; i++) temp.m[i][i] = 1; while(p > 0) { if(p & 1) temp = mult(temp, a); a = mult(a, a); p>>=1; } return temp; } int solve() { int i, j, k; mapper.clear(); scanf("%d%d", &n, &t); memset(rel.m, 0, sizeof(rel.m)); memset(ia, 0, sizeof(ia)); indexnum = 0; string name; map<string, int>::iterator iter; int index1 = 0, index2 = 0; for(i = 0; i < n; i++) { cin>>name; if((iter = mapper.find(name)) == mapper.end()) mapper[name] = index1 = indexnum++; else index1 = iter->second; int relnum = 0; cin>>ia[index1]>>relnum; ia[index1] = ia[index1] % 2; for(j = 0; j < relnum; j++) { cin>>name; if((iter = mapper.find(name)) == mapper.end()) mapper[name] = index2 = indexnum++; else index2 = iter->second; rel.m[index1][index2] = (rel.m[index1][index2] + 1) % 2; } rel.m[index1][index1] = (rel.m[index1][index1] + 1) % 2; } //for(i = 0; i < n; i++) // rel.m[i][i] = (rel.m[i][i] + 1) % 2; rel = pow(rel, t - 1); memset(res, 0, sizeof(res)); for(i = 0; i < n; i++) for(j = 0; j < n; j++) res[i] = (res[i] + ia[j] * rel.m[j][i]) % 2; int total = 0; //统计winner的个数 for(i = 0; i < n; i++) if(res[i] == 1) total++; return total; } int main() { int caseN; cin>>caseN; while(caseN--) cout<<solve()<<endl; return 0; }

你可能感兴趣的:(list,Integer,iterator,input,each,Matrix)