Tom and Jerry are playing a game with tubes and pearls. The rule of the game is:
1) Tom and Jerry come up together with a number K.
2) Tom provides N tubes. Within each tube, there are several pearls. The number of pearls in each tube is at least 1 and at most N.
3) Jerry puts some more pearls into each tube. The number of pearls put into each tube has to be either 0 or a positive multiple of K. After that Jerry organizes these tubes in the order that the first tube has exact one pearl, the 2nd tube has exact 2 pearls, …, the Nth tube has exact N pearls.
4) If Jerry succeeds, he wins the game, otherwise Tom wins.
Write a program to determine who wins the game according to a given N, K and initial number of pearls in each tube. If Tom wins the game, output “Tom”, otherwise, output “Jerry”.
Input
The first line contains an integer M (M<=500), then M games follow. For each game, the first line contains 2 integers, N and K (1 <= N <= 100, 1 <= K <= N), and the second line contains N integers presenting the number of pearls in each tube.
Output
For each game, output a line containing either “Tom” or “Jerry”.
Sample Input
2 5 1 1 2 3 4 5 6 2 1 2 3 4 5 5
Sample Output
Jerry Tom
题解:
网络流嘛,重在建模。我们可以把行中和列中相连或者中间隔有 ‘o’ 的 ‘*’ 点看做一个集合。分别按行和按列扫一遍得到行方向和列方向上的集合,并用boardx[][]和boardy[][]分别存储图中点所属的行列集合编号,然后我们就可以用超级原点和超级汇点分别连接boardx,boardy中的集合,如果一个点在boardx和boardy中都属于集合,代表存在行集合和列集合交叉点则可以建立行集合和列集合之间的边。这里的边flow皆为1。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int MAXN = 55;
const int INF = 0x3f3f3f3f;
struct Edge{
int flow,to,rev;
Edge(){}
Edge(int a,int b,int c):to(a),flow(b),rev(c){}
};
vector<Edge> E[MAXN*MAXN];
void Add(int from,int to,int flow){
E[from].push_back(Edge(to,1,E[to].size()));
E[to].push_back(Edge(from,0,E[from].size()-1));
}
int boardx[MAXN][MAXN],boardy[MAXN][MAXN];
char map[MAXN][MAXN];
inline void init(){
memset(boardx,0,sizeof boardx);
memset(boardy,0,sizeof boardy);
}
int deep[MAXN*MAXN];
bool BFS(int from,int to){
memset(deep,-1,sizeof deep);
deep[from] = 0;
queue<int> Q;
Q.push(from);
while(!Q.empty()){
int t = Q.front();
Q.pop();
for(int i=0 ; i<E[t].size() ; ++i){
Edge& e = E[t][i];
if(e.flow > 0 && deep[e.to] == -1){
deep[e.to] = deep[t] + 1;
Q.push(e.to);
}
}
}
return deep[to] != -1;
}
int iter[MAXN*MAXN];
int DFS(int from,int to,int flow){
if(from == to || flow == 0)return flow;
for(int &i=iter[from] ; i<E[from].size() ; ++i){
Edge &e = E[from][i];
if(e.flow > 0 && deep[e.to] == deep[from]+1){
int nowflow = DFS(e.to,to,min(flow,e.flow));
if(nowflow > 0){
e.flow -= nowflow;
E[e.to][e.rev].flow += nowflow;
return nowflow;
}
}
}
return 0;
}
int Dinic(int from,int to){
int sumflow = 0;
while(BFS(from,to)){
memset(iter,0,sizeof iter);
int t;
while((t=DFS(from,to,INF)) > 0)sumflow += t;
}
return sumflow;
}
int main(){
int T,M,N;
scanf("%d",&T);
while(T--){
init();
scanf("%d %d",&N,&M);
for(int i=0 ; i<N ; ++i)scanf("%s",&map[i]);
int num = 0;
for(int i=0 ; i<N ; ++i){
for(int j=0 ; j<M ; ++j){
if(map[i][j] == '*'){
++num;
Add(0,num,1);
while(j<M && map[i][j]!='#'){
if(map[i][j]!='o')boardx[i][j] = num;
++j;
}
}
}
}
for(int j=0 ; j<M ; ++j){
for(int i=0 ; i<N ; ++i){
if(map[i][j] == '*'){
++num;
Add(num,MAXN*MAXN-1,1);
while(i<N && map[i][j]!='#'){
if(map[i][j]!='o')boardy[i][j] = num;
++i;
}
}
}
}
for(int i=0 ; i<N ; ++i){
for(int j=0 ; j<M ; ++j){
if(boardx[i][j] && boardy[i][j])Add(boardx[i][j],boardy[i][j],1);
}
}
printf("%d
",Dinic(0,MAXN*MAXN-1));
for(int i=0 ; i<MAXN*MAXN ; ++i)E[i].clear();
}
return 0;
}