HDU 5495 LCS(其实就是找环)——BestCoder Round #58(div.1 div.2)

LCS

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)


Problem Description
You are given two sequence  {a1,a2,...,an}      and  {b1,b2,...,bn} .    Both sequences are permutation of  {1,2,...,n} .    You are going to find another permutation  {p1,p2,...,pn}      such that the length of LCS (longest common subsequence) of  {ap1,ap2,...,apn}      and  {bp1,bp2,...,bpn}      is maximum.
 

Input
There are multiple test cases. The first line of input contains an integer  T , indicating the number of test cases. For each test case:

The first line contains an integer  n(1n105)  - the length of the permutation. The second line contains  n  integers  a1,a2,...,an .    The third line contains  n integers  b1,b2,...,bn .

The sum of  n  in the test cases will not exceed  2×106 .
 

Output
For each test case, output the maximum length of LCS.
 

Sample Input
   
   
   
   
2 3 1 2 3 3 2 1 6 1 5 3 2 6 4 3 6 2 4 5 1
 

Sample Output
   
   
   
   
2 4
 

Source
BestCoder Round #58 (div.2)
 

/************************************************************************/

附上该题对应的中文题

LCS

 
 
 Time Limit: 6000/3000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
你有两个序列\{a_1,a_2,...,a_n\}{a1,a2,...,an}\{b_1,b_2,...,b_n\}{b1,b2,...,bn}. 他们都是11nn的一个排列. 你需要找到另一个排列\{p_1,p_2,...,p_n\}{p1,p2,...,pn}, 使得序列\{a_{p_1},a_{p_2},...,a_{p_n}\}{ap1,ap2,...,apn}\{b_{p_1},b_{p_2},...,b_{p_n}\}{bp1,bp2,...,bpn}的最长公共子序列的长度最大.
输入描述
输入有多组数据, 第一行有一个整数TT表示测试数据的组数. 对于每组数据:

第一行包含一个整数n (1 \le n \le 10^5)n(1n105), 表示排列的长度. 第2行包含nn个整数a_1,a_2,...,a_na1,a2,...,an. 第3行包含nn个整数 b_1,b_2,...,b_nb1,b2,...,bn.

数据中所有nn的和不超过2 \times 10^62×106.
输出描述
对于每组数据, 输出LCS的长度.
输入样例
2
3
1 2 3
3 2 1
6
1 5 3 2 6 4
3 6 2 4 5 1
输出样例
2
4
/****************************************************/

出题人的解题思路:

Problem 1. LCS

题目中给出的是两个排列, 于是我们我们可以先把排列分成若干个环, 显然环与环之间是独立的. 事实上对于一个长度为l (l > 1)l(l>1)的环, 我们总可以得到一个长度为l-1l1的LCS, 于是这个题的答案就很明显了, 就是nn减去长度大于11的环的数目.

首先,我们要搞清楚一个长度为L(L>1)的环,可以得到长度为L-1的最长公共子序列
例如样例2中
1 3 2 4
3 2 4 1
最长公共子序列为3 2 4,长度为4-1=3
而长度为1的的环则最长公共子序列为1
不同环之间是互不影响的,这个稍微想想就可以明白的
依旧拿样例2来说明,
5 6
6 5
最长公共子序列为1,可以是5,也可以是6,那把这加在之前的环后面,最长公共子序列长度就为4
1 3 2 4 5 6
3 2 4 1 6 5
所以我们只要找出所有的环,长度L>1的算L-1,否则算1
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 100005;
const int inf = 1000000000;
const int mod = 2009;
struct node
{
    int a,b;
}s[N];
bool cmp(node x,node y)
{
    return x.a<y.a;
}
bool v[N];
int main()
{
    int t,i,n,p,l,ans;
    scanf("%d",&t);
    while(t--)
    {
        memset(v,false,sizeof(v));
        scanf("%d",&n);
        ans=0;
        for(i=1;i<=n;i++)
            scanf("%d",&s[i].a);
        for(i=1;i<=n;i++)
            scanf("%d",&s[i].b);
        sort(s+1,s+n+1,cmp);
        for(i=1;i<=n;i++)
            if(!v[i])
            {
                p=i,l=1;
                while(s[p].b!=i)
                    l++,p=s[p].b,v[p]=true;
                v[i]=true;
                //printf("#%d %d#\n",i,l);
                ans+=l>1?l-1:1;
            }
        printf("%d\n",ans);
    }
    return 0;
}
菜鸟成长记

你可能感兴趣的:(ACM)