Codeforces 463D Gargari and Permutations:隐式图dp多串LCS
Posted Leohh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 463D Gargari and Permutations:隐式图dp多串LCS相关的知识,希望对你有一定的参考价值。
题目链接:http://codeforces.com/problemset/problem/463/D
题意:
给你k个1到n的排列,问你它们的LCS(最长公共子序列)是多长。
题解:
因为都是1到n的排列,即每个串中,1到n每个数字恰好出现一次。
将相同的数字之间相连,可以得到下面的样子(n = 4, k = 3):
显然,要求的LCS就等于图中互不相交的最多连线个数。
将每一个数字看做一个节点。
若i到j有一条有向边,则代表:
数字j的连线在i的连线的后面,且互不相交。
即:
若i->j,则要满足所有的pos[k][i] <= pos[k][j]。
其中pos[k][i]表示第k个串中,数字i出现的位置。
O(N^2*K)建图,最终得到的一定是一个有向无环图。
LCS就等于这个图上的最长路径长度。
所以dfs跑一边dp就行了。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define MAX_N 1005 6 #define MAX_K 10 7 8 using namespace std; 9 10 int n,k; 11 int dp[MAX_N]; 12 int a[MAX_K][MAX_N]; 13 int pos[MAX_K][MAX_N]; 14 vector<int> edge[MAX_N]; 15 16 void read() 17 { 18 cin>>n>>k; 19 for(int i=1;i<=k;i++) 20 { 21 for(int j=1;j<=n;j++) 22 { 23 cin>>a[i][j]; 24 pos[i][a[i][j]]=j; 25 } 26 } 27 } 28 29 bool is_valid(int x,int y) 30 { 31 for(int i=1;i<=k;i++) 32 { 33 if(pos[i][x]>=pos[i][y]) return false; 34 } 35 return true; 36 } 37 38 void build() 39 { 40 for(int i=1;i<=n;i++) 41 { 42 for(int j=1;j<=n;j++) 43 { 44 if(is_valid(i,j)) edge[i].push_back(j); 45 } 46 } 47 } 48 49 void dfs(int now) 50 { 51 dp[now]=1; 52 for(int i=0;i<edge[now].size();i++) 53 { 54 int temp=edge[now][i]; 55 if(dp[temp]==-1) dfs(temp); 56 dp[now]=max(dp[now],dp[temp]+1); 57 } 58 } 59 60 void work() 61 { 62 build(); 63 memset(dp,-1,sizeof(dp)); 64 int ans=0; 65 for(int i=1;i<=n;i++) 66 { 67 if(dp[i]==-1) dfs(i); 68 ans=max(ans,dp[i]); 69 } 70 cout<<ans<<endl; 71 } 72 73 int main() 74 { 75 read(); 76 work(); 77 }
以上是关于Codeforces 463D Gargari and Permutations:隐式图dp多串LCS的主要内容,如果未能解决你的问题,请参考以下文章
[CF463D] Gargari and Permutations - dp
CF463D Gargari and Permutations dp
CF 463D Gargari and Permutations [dp]
CF463D Gargari and Permutations (LCS)