原题传送门
确实是一道不错的题目
发现k特别小
可以先
O
(
n
2
)
O(n^2)
O(n2)枚举
x
,
y
x,y
x,y,若
x
x
x在每个数列中都在
y
y
y前面,那么
x
x
x就可以向
y
y
y连一条边,这样建图建好以后整个图是一个
D
A
G
DAG
DAG,跑一个拓扑DP就好了
Code:
#include <bits/stdc++.h>
#define maxn 1000010
#define _ 0
using namespace std;
struct Edge{
int to, next;
}edge[maxn << 1];
int num, head[maxn], n, k, pos[1010][6], in[maxn], dp[maxn];
queue <int> q;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y){ edge[++num] = (Edge){y, head[x]}, head[x] = num; }
int main(){
n = read(), k = read();
for (int i = 1; i <= k; ++i)
for (int j = 1; j <= n; ++j) pos[read()][i] = j;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (i != j){
int flag = 1;
for (int l = 1; l <= k; ++l)
if (pos[i][l] > pos[j][l]){ flag = 0; break; }
if (flag){
++in[j]; addedge(i, j);
}
}
for (int i = 1; i <= n; ++i)
if (!in[i]) q.push(i), dp[i] = 1;
while (!q.empty()){
int u = q.front(); q.pop();
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (dp[v] < dp[u] + 1) dp[v] = dp[u] + 1;
if (!(--in[v])) q.push(v);
}
}
int ans = 0;
for (int i = 1; i <= n; ++i) ans = max(ans, dp[i]);
printf("%d\n", ans);
return 0 ^ _ ^ 0;
}