题意:
给一个n维的东西,若一个的n维都小于另一个的n维,则其可嵌套。
求最长可嵌套的有几个,并打印出路径。
解析:
DAG上的最长路,先将可嵌套的图标记g[i][j] = 1,然后枚举起点记忆化搜索扫一遍就行了。
打印的时候,找到起点,打印即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
using namespace std;
const int maxn = 30 + 10;
int n, k;
int box[maxn][maxn];
int g[maxn][maxn];
int dis[maxn];
bool is_ok(int a[], int b[])
{
for (int i = 0; i < k; i++)
if (a[i] >= b[i])
return false;
return true;
}
int dfs(int i)
{
int& res = dis[i];
if (0 < res)
return res;
res = 1;
for (int j = 1; j <= n; j++)
{
if (g[i][j])
{
res = max(res, dfs(j) + 1);
}
}
return res;
}
void print_path(int i)
{
printf("%d ", i);
for (int j = 1; j <= n; j++)
{
if (g[i][j] && dis[i] == dis[j] + 1)
{
print_path(j);
break;
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (~scanf("%d %d", &n, &k))
{
memset(g, 0, sizeof(g));
memset(dis, 0, sizeof(dis));
memset(box, 0, sizeof(box));
for (int i = 1; i <= n; i++)
{
for(int j = 0; j < k; j++)
{
scanf("%d", &box[i][j]);
}
sort(box[i], box[i] + k);
// for(int j = 0; j < k; j++)
// {
// printf("%d ", box[i][j]);
// }
}
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)
{
if (is_ok(box[i], box[j]))
g[i][j] = 1;
if (is_ok(box[j], box[i]))
g[j][i] = 1;
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
dis[i] = dfs(i);
int pos = 0;
for (int i = 1; i <= n; i++)
{
if (ans < dis[i])
{
pos = i;
ans = dis[i];
}
}
printf("%d\n", ans);
print_path(pos);
printf("\n");
}
return 0;
}