洛谷P1983 [NOIP2013 普及组] 车站分级 题解

思路

由题可知,在一趟车次的区间内,停靠的站点的等级恒大于不停靠的站点。
因此,对于每一趟车次的区间,给所有停靠的站点向所有不停靠的站点两两连有向边,然后求图中最长的路径长度,就能得到答案。

实现

因为可能出现重边,而且\(n\le1000\),所以在处理车次连边的时候使用邻接矩阵,再改成邻接表。
之后将入度为0的节点的等级设置为1(其实应该反着来,这样分出来的等级更符合逻辑,但是我是正着来的),遍历整张图。对于每一个节点,其等级为指向它的节点度数的最大值+1,即$$\large level_v=max(u)+1,(u,v)\in E$$
考虑对图进行拓扑排序,然后递推。然后我悲催地发现我已经把拓扑排序忘光了

代码

#include <cstdio>
#include <cstring>
#define N 1005
#define max(x,y) ((x)>(y)?(x):(y))
int s[N];
int u[N];
int f[N][N];
struct node
{
	int lvl,in,out;
	int nx[N];
} a[N];
int a2[N];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		a[i].lvl=1;
	for(int i=1;i<=m;i++)
	{
		memset(s,0,sizeof(s));
		int l;
		scanf("%d",&l);
		for(int j=1;j<=l;j++)
		{
			scanf("%d",&u[j]);
			s[u[j]]=1;
		}
		for(int j=u[1];j<=u[l];j++)
			if(!s[j])
				for(int k=1;k<=l;k++)
					f[u[k]][j]=1;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(f[i][j])
			{
				a[i].nx[++a[i].out]=j;
				a[j].in++;
			}
	int cnt=0;
	for(int i=1;i<=n;i++)
		if(!a[i].in)
			a2[++cnt]=i;
	for(int h=1,t=cnt;h<=t;h++)
		for(int k=1;k<=a[a2[h]].out;k++)
			if(!--a[a[a2[h]].nx[k]].in)
				a2[++t]=a[a2[h]].nx[k];
	for(int i=1;i<=n;i++)
	{
		int k=a2[i];
		for(int j=1;j<=a[k].out;j++)
			a[a[k].nx[j]].lvl=max(a[a[k].nx[j]].lvl,a[k].lvl+1);
	}
	int ans=0;
	for(int i=1;i<=n;i++)
		ans=max(ans,a[i].lvl);
	printf("%d",ans);
}

很冗杂凑合看吧

posted @ 2024-08-18 21:30  整齐的艾萨克  阅读(15)  评论(0编辑  收藏  举报