洛谷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);
}
很冗杂凑合看吧