1651. Shortest Subchain

http://acm.timus.ru/problem.aspx?space=1&num=1651

题意:给出链上点的顺序  要求找一条子链 满足三个条件

1,起点和终点和原链一样

2,边的顺序和原始顺序一致

3,最短

思路:

如果去掉第二个条件的话 就变成了最简单的最短路了  由于第二个条件的限制 要按给的边的顺序依次更新

然后重要的就是记录路径

代码及其注释:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<string>

#include<vector>

#include<map>

#include<queue>

#include<stack>

#include<cmath>

#define LL long long

//#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;



const int INF=0x3f3f3f3f;

const int N=10005;

vector<int>dist[N];//到节点 i 的最优距离 如果有更新就不断在后面累计

vector<int>f1[N];//到节点 i 第 j 个最优更新 的上一个节点

vector<int>f2[N];//到节点 i 第 j 个最优更新 的上一个节点的第几个更新

int a[N*10];//注意大小

void sovle(int n)

{

    dist[a[1]].push_back(0);

    f1[a[1]].push_back(-1);

    f2[a[1]].push_back(-1);

    for(int i=2;i<=n;++i)

    {

        int l1=dist[a[i]].size();

        int l2=dist[a[i-1]].size();

        if((l1==0)||(dist[a[i]][l1-1]>dist[a[i-1]][l2-1]+1))//可继续更新

        {

            dist[a[i]].push_back(dist[a[i-1]][l2-1]+1);//在后面累计

            f1[a[i]].push_back(a[i-1]);//记录路径

            f2[a[i]].push_back(l2-1);//记录路径

        }

    }

}

void dfs(int x,int k)

{

    if(f1[x][k]!=-1)

    dfs(f1[x][k],f2[x][k]);

    cout<<x<<" ";

}

int main()

{

    //freopen("data.txt","r",stdin);

    int n;

    cin>>n;

    for(int i=1;i<=n;++i)

    cin>>a[i];

    if(a[1]==a[n])

    {cout<<a[1]<<endl;return 0;}//首尾一样的情况

    sovle(n);

    dfs(a[n],dist[a[n]].size()-1);

    cout<<endl;

    return 0;

}

 

你可能感兴趣的:(chain)