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;
}
浙公网安备 33010602011771号