https://www.luogu.org/problemnew/show/P1983
因为题目中说了,每一条路径满足一点:经过但不停留的车站的等级一定小于这条路径所停留的车站的等级。所以我们可以根据这个确定如下关系:
假设数组存车站等级,当前有一条路径,那么我们便可以确认。(特别注意:单凭这么一条路径你无法确认和之间的关系)。那么我们就根据这个关系连两条边和(写在前面的是起点,后面的是终点)。
照着如上方式不断连边(建新图),建好的新图上的最长路径经过的点的总个数即为答案。实际写的时候是用的拓扑排序+DAG上DP实现的。这是由于每一趟车次经过的点的编号顺序一定是呈升序,所以说新图一定是个DAG。
AC Code:
#include<cstdio>
#include<iostream>
#define ri register int
using namespace std;
const int MAXN=1020;
int n,m,stot,now,que[MAXN],had[MAXN][MAXN],u[MAXN*MAXN],v[MAXN*MAXN],w[MAXN*MAXN],fst[MAXN*MAXN],nxt[MAXN*MAXN];
int dis[MAXN],book[MAXN],t,sta[MAXN],ans;
void dfs(int x)
{
book[x]=1;
for(ri k=fst[x];k>0;k=nxt[k])
if(!book[v[k]]) dfs(v[k]);
sta[--t]=x;
}
void build()
{
for(ri k=1;k<=stot;k++)
{
scanf("%d",&now);
for(ri i=1;i<=now;i++)
{
scanf("%d",&que[i]);
book[que[i]]=1;
}
for(ri i=que[1]+1;i<=que[now]-1;i++)
{
if(!book[i])
{
for(ri j=1;j<=now;j++)
{
if(had[i][que[j]]) continue;
m++;
u[m]=i,v[m]=que[j],had[i][que[j]]=1;
nxt[m]=fst[u[m]],fst[u[m]]=m;
}
}
}
for(ri i=1;i<=now;i++) book[que[i]]=0;
}
}
int main()
{
scanf("%d%d",&n,&stot);
build();
t=n+1;
for(ri i=1;i<=n;i++)
if(!book[i]) dfs(i);
for(ri i=1;i<=n;i++)
{
int x=sta[i];//sta数组存储新图的拓扑序
for(ri k=fst[x];k>0;k=nxt[k])
dis[v[k]]=max(dis[v[k]],dis[u[k]]+1);
}
for(ri i=1;i<=n;i++) ans=max(ans,dis[i]+1);
cout<<ans;
return 0;
}