题目来源:http://codeforces.com/problemset/problem/463/D
题意:给你k(k<=5)个串,每个串的长度为n,且是1~n的全排列,求这k个串的最长公共子序列。
思路:对于1~n中的任意数i和j,如果在所有k个串中,均满足i的顺序在j前面,我们可以记作i->j。最长公共子序列即是找一条最长的路径,满足a1->a2->a3->...->am,这样就能将其转化成拓扑排序问题,找一条有向图的最长路径。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
const int maxn = 10010;
int a[10][maxn], p[10][maxn], n, K;
int head[maxn];
struct data {
int to, next;
} e[maxn * 110];
int cnt;
int du[maxn];
void ins(int x, int y) {
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
}
queue<int> q, P;
int main() {
__;
cin >> n >> K;
for (int i = 1; i <= K; ++i) {
for (int j = 1; j <= n; ++j) {
cin >> a[i][j];
p[i][a[i][j]] = j;
}
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j)
if (i != j) {
bool ok = 1;
for (int k = 1; k <= K; ++k) {
if (p[k][i] < p[k][j]);
else {
ok = 0;
break;
}
}
if (ok) {
ins(i, j);
du[j]++;
}
}
}
for (int i = 1; i <= n; ++i) {
if (du[i] == 0)q.push(i);
}
int tot = 0;
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = head[x]; i; i = e[i].next) {
du[e[i].to]--;
if (du[e[i].to] == 0) {
P.push(e[i].to);
}
}
if (q.empty()) {
swap(P, q);
++tot;
}
}
cout << tot << endl;
return 0;
}