#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
#include <climits>

using namespace std;

struct Edge {
	int from, to, flow, cap, revInd;
	Edge(int from, int to, int flow, int cap, int revInd) : from(from), to(to), 
	flow(flow), cap(cap), revInd(revInd) {}
};

class EKFlow {
  protected:
	int n, src, dest, totalFlow;
	vector<Edge> edge;
	vector<vector<int>> G;
	vector<unordered_map<int, int>> flowLookup;

	vector<int> lastEdge;

	virtual bool findPath() {
		for (int i = 1; i <= n; ++i) {
			lastEdge[i] = -2;
		}
		queue<int> Q;
		lastEdge[src] = -1;
		Q.push(src);

		while (!Q.empty()) {
			int x = Q.front();
			Q.pop();

			for (auto ind : G[x]) {
				auto& e = edge[ind];
				if (e.flow != e.cap && lastEdge[e.to] == -2) {
					Q.push(e.to);
					lastEdge[e.to] = ind;

					if (e.to == dest) {
						return true;
					}
				}
			}
		}

		return false;
	}

	void updateLookup(int x, int y, int newFlow) {
		if (!flowLookup[x].empty()) {
			flowLookup[x][y] += newFlow;
		}
		if (!flowLookup[y].empty()) {
			flowLookup[y][x] -= newFlow;
		}
	}

  public:
	EKFlow(int n, int src, int dest) : n(n), src(src), dest(dest) {
		totalFlow = 0;
		G.resize(n+1);
		flowLookup.resize(n+1);
		lastEdge.resize(n+1, -2);
	}

	bool runUnit() {
		if (findPath()) {
			for (int x = dest; x != src; x = edge[lastEdge[x]].from) {
				auto& e = edge[lastEdge[x]];
				e.flow += 1;
				edge[e.revInd].flow -= 1;
			}
			totalFlow += 1;
			return true;
		}
		return false;
	}

	virtual int runPath() {
		if (findPath()) {
			int newFlow = INT_MAX;
			for (int x = dest; x != src; x = edge[lastEdge[x]].from) {
				auto& e = edge[lastEdge[x]];
				newFlow = min(newFlow, e.cap - e.flow);
			}
			totalFlow += newFlow;
			for (int x = dest; x != src; x = edge[lastEdge[x]].from) {
				updateLookup(edge[lastEdge[x]].from, x, newFlow);
				auto& e = edge[lastEdge[x]];
				e.flow += newFlow;
				edge[e.revInd].flow -= newFlow;
			}
			return newFlow;
		}
		return 0;
	}

	virtual void addEdge(int x, int y, int cap, int flow=0) {
		while (x > n || y > n) {
			++n;
			G.push_back(vector<int>());
			flowLookup.push_back(unordered_map<int, int>());
			lastEdge.push_back(-2);
		}

		int sz = edge.size();
		edge.push_back(Edge(x, y, flow, cap, sz+1));
		edge.push_back(Edge(y, x, -flow, 0, sz));

		G[x].push_back(sz);
		G[y].push_back(sz+1);
	}

	int getFlow(int x, int y) {
		if (flowLookup[x].empty()) {
			for (auto ind : G[x]) {
				flowLookup[x][edge[ind].to] += edge[ind].flow;
			}
		}
		auto it = flowLookup[x].find(y);
		if (it == flowLookup[x].end()) {
			return 0;
		}
		return it->second;
	}

	int runFlow() {
		for (; runPath(););
		return totalFlow;
	}

	int getTotalFlow() {
		return totalFlow;
	}
};

void solve() {
	int n, k;
	cin >> n >> k;

	vector<string> name(n+1);
	vector<int> who(k+1);
	vector<vector<int>> sub(n+1, vector<int>(k+1));

	EKFlow max_flow(n+k+2, 1, 2);

	for (int i = 1; i <= n; ++i) {
		max_flow.addEdge(1, 2+i, 1);
	}
	for (int i = 1; i <= k; ++i) {
		max_flow.addEdge(2+n+i, 2, 1);
	}

	for (int i = 1; i <= n; ++i) {
		cin >> name[i];
		for (int j = 1; j <= k; ++j) {
			cin >> sub[i][j];
		}

		for (int j = 1; j <= k; ++j) {
			if (j > 2 && sub[i][j] > sub[i][j-1] && sub[i][j-1] > sub[i][j-2]) {
				max_flow.addEdge(2+i, 2+n+j, 1);
			}
		}
	}

	max_flow.runFlow();

	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= k; ++j) {
			if (max_flow.getFlow(2+i, 2+n+j) == 1) {
				who[j] = i;
			}
		}
	}

	for (int i = 1; i <= k; ++i) {
		if (who[i] == 0) {
			cout << "none\n";
		} else {
			cout << name[who[i]] << "\n";
		}
	}
}

int main() {
	int tests = 1;

	for (;tests; --tests) {
		solve();
	}
}