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;
}

 

posted on 2012-10-24 16:08  夜->  阅读(316)  评论(0编辑  收藏  举报