洛谷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); }
很冗杂凑合看吧
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效