#include #include #include #include #include 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; vector> G; vector> flowLookup; vector lastEdge; virtual bool findPath() { for (int i = 1; i <= n; ++i) { lastEdge[i] = -2; } queue 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()); flowLookup.push_back(unordered_map()); 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 name(n+1); vector who(k+1); vector> sub(n+1, vector(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(); } }