题面:https://www.luogu.org/problem/P1983

首先我们来谈一谈邻接表+dfs:
假设有一辆车经过三个车站ai,aj,ak(ai,aj,ak车站编号递增)
那么在ai,aj之间的a(i+1),a(i+2),.......,a(j-1)的级别一定是严格小于ai和aj的级别的
同理,在aj,ak之间的a(j+1),a(j+2),.......,a(k-1)的级别也一定是严格小于aj,ai的级别的
那么我么可以得出,在ai,ak之间的a(i+1),a(i+2),......,a(j-1),a(j+1),........a(k-1)的级别一定是严格小于ai,aj和ak的级别的
如果你还没看明白,那么我们再反过来看,
ai,aj和ak的级别一定是严格大于在ai,ak之间的a(i+1),a(i+2),......,a(j-1),a(j+1),........a(k-1)的级别的.
看到这个,我们是不是很容易就能够想到将整个行进路线转为一个有向图,
将所有小于ai,aj,ak级别的车站都和ai,aj,ak连接加一条边,再将所有入度为0的跑一边dfs即可
这里要注意了,光是dfs会超时,所以必须要用记忆化搜索来做Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
const int N=1000005,M=1005;//注意这里需要将数组开到2*N,否则会爆,二维数组开到N即可
long long n,m,s,x[N],to,head[N],j,a,k,ans,dp[N],i;
bool used[M][M];
struct node{long long u,v,next,id;
}edge[N];
void push(long long u,long long v){to++;edge[to].next=head[u];edge[to].u=u;edge[to].v=v;head[u]=to;edge[v].id++;//统计入度used[u][v]=true;//因为这里会出现重边现象,所以每次做加边操作后要将这条边标记一下}//邻接表,就不需我多做叙述了吧
long long dfs(long long u){//记忆化搜索long long l;if(dp[u]!=-1){//记搜的标志return dp[u];}dp[u]=1;for(l=head[u];l!=-1;l=edge[l].next){//邻接表中的所有元素顺序枚举dp[u]=max(dp[u],dfs(edge[l].v)+1);//方程:f(i)=max{f(j)+1};}return dp[u];
}
int main(){memset(head,-1,sizeof(head));scanf("%lld%lld",&n,&m);for(i=1;i<=m;i++){scanf("%lld",&s);for(j=1;j<=s;j++){scanf("%lld",&x[j]);}for(j=2;j<=s;j++){for(k=x[j-1]+1;k<x[j];k++){//枚举在x[j-1]和x[j]之间的所有小于x[j],x[j-1]级别的车站for(a=1;a<=s;a++){if(!used[x[a]][k]){//如果不是重边push(x[a],k);//当前枚举到的车站与所有车站加边}}}}}memset(dp,-1,sizeof(dp));//因为要取最大值,所以初始值全部为-1for(i=1;i<=n;i++){if(edge[i].id==0){//如果当前入度为0ans=max(ans,dfs(i));//每次跑一边dfs就行}}printf("%lld\n",ans);//输出ansreturn 0;
}接着,我们再来看拓扑排序的做法 其实,拓扑排序本质上就是找到一个入度为0的点然后输出,接着从网中删除此顶点及所有出边,直到不存在入度为0的点结束,
那么,我们就可以直接统计一下到底进行了几次拓扑排序,也就是经几次以上操作后不存在入度为0的点了.
虽然拓扑排序算法复杂度高,不易理解,效率也不容乐观,但是我们还是要写一写滴.Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
const int N=1000005,M=1005;
long long n,m,s,x[N],to,head[N],j,a,k,ans,i,top,vis[N],q[N];
bool used[M][M];
struct node{long long u,v,next,id;
}edge[N];
void push(long long u,long long v){to++;edge[to].next=head[u];edge[to].u=u;edge[to].v=v;head[u]=to;edge[v].id++;//统计入度used[u][v]=true;//因为这里会出现重边现象,所以每次做加边操作后要将这条边标记一下}//邻接表,就不需我多做叙述了吧int main(){freopen("level.in","r",stdin);freopen("level.out","w",stdout);memset(head,-1,sizeof(head));scanf("%lld%lld",&n,&m);for(i=1;i<=m;i++){scanf("%lld",&s);for(j=1;j<=s;j++){scanf("%lld",&x[j]);}for(j=2;j<=s;j++){for(k=x[j-1]+1;k<x[j];k++){//枚举在x[j-1]和x[j]之间的所有小于x[j],x[j-1]级别的车站for(a=1;a<=s;a++){if(!used[x[a]][k]){//如果不是重边push(x[a],k);//当前枚举到的车站与所有车站加边}}}}}
//之前部分不变,判重边,加边,记录入度while(1){//拓扑排序top=0;for(i=1;i<=n;i++){if(!vis[i]&&!edge[i].id){//如果此点入度为0且没有被访问过q[++top]=i;//q是一个栈数组,记录此次找到的入度为0的点vis[i]=1;//标记为已经访问过了}}if(!top){//如果栈是空的,即没有找到入度为0的点,那么说明拓扑排序已经进行完毕,退出循环break;}for(k=1;k<=top;k++){//枚举栈里的所有元素for(i=1;i<=n;i++){if(used[q[k]][i]){//如果有这条边used[q[k]][i]=0;//把这条边删除edge[i].id--;//入度--}}}ans++;//操作次数++}printf("%lld\n",ans);//输出ansreturn 0;
}

转载于:https://www.cnblogs.com/ukcxrtjr/p/11382412.html

P1983 车站分级相关推荐

  1. P1983 车站分级(拓扑排序)

    车站分级 题目传送门 解题思路 这题就是用拓扑排序分层 首先是建图 每进行一次输入,就将没有停靠的站与停靠的站都建立一条边 因为题目样例不怎么大,所以可以用邻接矩阵 for(int i=1;i< ...

  2. 洛谷 P1983 车站分级(拓扑排序)

    https://www.luogu.com.cn/problem/P1983 思路 对于每一趟车,将其经过的车站中,停靠的和不停靠的连一条边,注意边的去重,要双向标记,不然有个点会超时,这样拓扑排序递 ...

  3. luogu P1983 车站分级

    题目描述 一条单向的铁路线上,依次有编号为 1, 2, -, n 的 n 个火车站.每个火车站都有一个级别,最低为 1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车 ...

  4. 洛谷 P1983 车站分级

    嗯... 听说这是一道存图+拓扑排序的题,但是看了一晚上好像只看出存图来.... 自己太蒟蒻,然后没办法,就.....就借用了Mr Kevin的代码和思路,然后自己做了一些了解... (并且现在自己对 ...

  5. 洛谷P1983 车站分级 拓扑排序

    题目链接:https://www.luogu.com.cn/problem/P1983 此题是用拓扑排序求层数,将等级高的点连向等级的点,连成的图用拓扑排序看一下多少层,即答案. 代码如下 #incl ...

  6. 洛谷P1983 车站分级(拓扑排序)

    [题目描述] 一条单向的铁路线上,依次有编号为 1 , 2 , - , n 1,2,\dots ,n 1,2,-,n的 n n n个火车站.每个火车站都有一个级别,最低为 1 1 1级.现有若干趟车次 ...

  7. 洛谷P1983 车站分级(图的建立)

    题目描述 一条单向的铁路线上,依次有编号为 1, 2, -, n的 n个火车站.每个火车站都有一个级别,最低为 1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站  ...

  8. 洛谷 P1983 车站分级

    题目描述 一条单向的铁路线上,依次有编号为 1, 2, -, n 的 n 个火车站.每个火车站都有一个级 别,最低为 1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车 次停靠了 ...

  9. 洛谷P1983 车站分级

    这题有三种做法 1.O(nm2)1.O(nm2)1.O(nm^2) 488ms / 9.61MB / 0.68KB 不用讲,直接贴代码 #include<bits/stdc++.h> us ...

最新文章

  1. css中“[]”、“”“~”、“,”、“+”和“”详解
  2. python3 多重列表推导式
  3. Android Broadcast编写的音乐播放器
  4. 朴素贝叶斯原理及实现
  5. 【Python 标准库学习】日期和时间处理库 — datetime
  6. iphone主屏幕动态壁纸_苹果11怎么设置动态壁纸?这个简单!只需这样操作
  7. Java-Runoob-高级教程-实例-字符串:14. Java 实例 - 连接字符串
  8. maven 压缩html,YUI Compressor Maven插件压缩 js、css并输出war包
  9. orc识别较慢_超强orc文字识别免注册版
  10. zzulioj1039答案C语言,ZZULIOJ 1037~1045(C语言)
  11. xshell报initialize flexnet service failed error code 50003错误
  12. Macbook 苹果电脑 安装搭建Vue脚手架教程m1芯片Vue脚手架初学
  13. 按键精灵 python加强版
  14. 如何选择数据拆分方法:不同数据拆分方法的优缺点及原因
  15. JavaMail IMAPFolder.getMessageByUID 获取QQ和腾讯企业邮箱新邮件的问题
  16. 1607_PC汇编语言_汇编语言简介
  17. 基于springboot+vue的疾病匿名检测查询系统
  18. KISS原则和YAGNI原则
  19. HashMap的存储
  20. 为什么浏览器打开一些网站会显示不安全

热门文章

  1. 2018,10,19模拟赛
  2. Java条形码生成(128c)
  3. jQuery Validate 提交表单验证失败扩展方法
  4. Java 两线程交替打印奇偶数(一)
  5. 《Python数据科学实践指南》——0.2节如何成为数据科学家
  6. 软件工程第一次作业补充
  7. Linux 修改yum 源
  8. jQuery的ajax()、post()方法提交数组,参数[] 问题
  9. iOS动画:UIView动画和CALayer动画(CABasicAnimation、CAKeyframeAnimation的使用)
  10. Artech的MVC4框架学习——第三章controller的激活