P1983 车站分级

https://www.luogu.org/problemnew/show/P1983

因为题目中说了,每一条路径满足一点:经过但不停留的车站的等级一定小于这条路径所停留的车站的等级。所以我们可以根据这个确定如下关系:

假设数组S存车站等级,当前有一条路径u->u+2,那么我们便可以确认S_{u+1}<S_{u},S_{u+1}<S_{u+2}。(特别注意:单凭这么一条路径你无法确认S_{u}S_{u+2}之间的关系)。那么我们就根据这个关系连两条边(u+1,u)(u+1,u+2)(写在前面的是起点,后面的是终点)。

照着如上方式不断连边(建新图),建好的新图上的最长路径经过的点的总个数即为答案。实际写的时候是用的拓扑排序+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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值