Codeforces 463D

题目链接

D. Gargari and Permutations
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Gargari got bored to play with the bishops and now, after solving the problem about them, he is trying to do math homework. In a math book he have found k permutations. Each of them consists of numbers 1, 2, ..., n in some order. Now he should find the length of the longest common subsequence of these permutations. Can you help Gargari?

You can read about longest common subsequence there:https://en.wikipedia.org/wiki/Longest_common_subsequence_problem

Input

The first line contains two integers n and k (1 ≤ n ≤ 1000; 2 ≤ k ≤ 5). Each of the next k lines contains integers 1, 2, ..., n in some order — description of the current permutation.

Output

Print the length of the longest common subsequence.

Sample test(s)
input
4 3
1 4 2 3
4 1 2 3
1 2 4 3
output
3
Note

The answer for the first test sample is subsequence [1, 2, 3].

题意:给出k个n的全排列,求k个串的最长公共子序列(1<= k <= 5).

刚拿到题感觉是个dp,但是又没有明确的思路,yy了两发,发现不对,就没有做了。

今天才知道这个题可以通过建图然后得到若干个DAG,然后求最长路。

让我想起了某此CF的C题。那题可以转化为求MST,万万没想到。

今天记下,以后应多往图这方面想,根据题意是否能构造出图来,然后我只想说题水人更水。

本题可以这样来构图,如果在每个序列中,i都在j前面,那么可以从i向j连一条边。

最后求以每个点为根的最长路,取最大值即可。

Accepted Code:

 1 /*************************************************************************
 2     > File Name: 463D.cpp
 3     > Author: Stomach_ache
 4     > Mail: sudaweitong@gmail.com
 5     > Created Time: 2014年08月31日 星期日 22时02分01秒
 6     > Propose: 
 7  ************************************************************************/
 8 
 9 #include <cmath>
10 #include <string>
11 #include <cstdio>
12 #include <vector>
13 #include <fstream>
14 #include <cstring>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18 /*Let's fight!!!*/
19 
20 #define rep(i, n) for (int i = (0); i < (n); i++)
21 #define FOR(i, n) for (int i = (1); i <= (n); i++)
22 int n, k;
23 int a[5][1005], dp[1005], pos[5][1005];
24 vector<int> G[1005];
25 bool vis[1005];
26 
27 bool check(int x, int y) {
28       rep (i, k) if (pos[i][x] > pos[i][y]) return false;
29     return true;
30 }
31 
32 void dfs(int u) {
33       if (vis[u]) return;
34     vis[u] = true;
35     int sz = (int)G[u].size();
36     rep (i, sz) {
37           int v = G[u][i];
38         dfs(v);
39         dp[u] = max(dp[u], dp[v]);
40     }
41     dp[u]++;
42 }
43  
44 int main(void) {
45     cin >> n >> k;
46     int a;
47     rep (i, k) rep(j, n) cin >> a, pos[i][a] = j;
48     FOR (i, n) FOR (j, n) if (i != j && check(i, j)) G[i].push_back(j);
49     
50 //    FOR (i, n) rep (j, G[i].size()) cerr << i << "-->" << G[i][j] << endl;
51 
52     memset(vis, false, sizeof(vis));
53     FOR (i, n) if (!vis[i]) dfs(i);
54 
55     int ans = 0;
56     FOR (i, n) ans = max(ans, dp[i]);
57     cout << ans << endl;
58     
59     return 0;
60 }

 

原文地址:https://www.cnblogs.com/Stomach-ache/p/3948334.html